diff --git a/gtk2_ardour/.cvsignore b/gtk2_ardour/.cvsignore new file mode 100644 index 0000000000..95bc1a733d --- /dev/null +++ b/gtk2_ardour/.cvsignore @@ -0,0 +1,7 @@ +ardour +ardourx +ardour.bin +version.h +version.cc +*.mo +*.pot diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript new file mode 100644 index 0000000000..6ee7c5701b --- /dev/null +++ b/gtk2_ardour/SConscript @@ -0,0 +1,227 @@ +# -*- python -*- + +import os +import os.path +import glob + +Import('env install_prefix final_prefix config_prefix libraries i18n version') + +gtkardour = env.Copy() + +# +# this defines the version number of the GTK interface to ardour +# + +domain = 'gtk_ardour' + +gtkardour.Append(DOMAIN=domain, MAJOR=1,MINOR=0,MICRO=0) +gtkardour.Append(CXXFLAGS="-DPACKAGE=\\\"" + domain + "\\\"") +gtkardour.Append(PACKAGE=domain) +gtkardour.Append(POTFILE=domain + '.pot') + +gtkardour.Merge ( [libraries['ardour2'], + libraries['gtkmm2ext'], + libraries['midi++2'], + libraries['pbd3'], + libraries['gtkmm2'], + libraries['sigc2'], + libraries['libgnomecanvasmm'], + libraries['sysmidi'], + libraries['sndfile'], + libraries['lrdf'], + libraries['glibmm2'], + libraries['pangomm'], + libraries['atkmm'], + libraries['gdkmm2'], + libraries['gtk2'], + libraries['libgnomecanvas2'], + libraries['xml'], + libraries['soundtouch'], + libraries['raptor'], + libraries['samplerate'], + libraries['jack']] + ) + +if gtkardour['VST']: + gtkardour.Merge ([ libraries['fst']]) + +gtkardour_files=Split(""" +add_route_dialog.cc +ardour_dialog.cc +ardour_message.cc +audio_clock.cc +automation_gain_line.cc +axis_view.cc +default_keys.cc +editing.cc +gain_automation_time_axis.cc +grouped_buttons.cc +gtk-custom-hruler.c +gtk-custom-ruler.c +keyboard.cc +keyboard_target.cc +meter_bridge_strip.cc +opts.cc +pan_automation_time_axis.cc +prompter.cc +redirect_automation_line.cc +redirect_automation_time_axis.cc +route_redirect_selection.cc +tempo_dialog.cc +time_selection.cc +version.cc +ardour_ui_dependents.cc +ardour_ui_mixer.cc +automation_pan_line.cc +curvetest.cc +editor_scrub.cc +ghostregion.cc +gtkscrolledwindow.c +imageframe_time_axis.cc +imageframe_time_axis_view.cc +imageframe_view.cc +marker.cc +marker_time_axis.cc +marker_time_axis_view.cc +marker_view.cc +public_editor.cc +region_gain_line.cc +region_selection.cc +selection.cc +ardour_ui_ed.cc +canvas-ruler.c +canvas-simpleline.c +canvas-simplerect.c +canvas-waveview.c +editor_audiotrack.cc +editor_canvas_events.cc +editor_cursors.cc +editor_export_audio.cc +editor_keys.cc +editor_nudge.cc +editor_timefx.cc +imageframe_time_axis_group.cc +send_ui.cc +time_axis_view.cc +editor_markers.cc +editor_tempodisplay.cc +main.cc +panner2d.cc +region_editor.cc +streamview.cc +utils.cc +automation_time_axis.cc +connection_editor.cc +crossfade_edit.cc +crossfade_view.cc +editor_hscroller.cc +editor_mixer.cc +imageframe_socket_handler.cc +location_ui.cc +route_ui.cc +time_axis_view_item.cc +visual_time_axis.cc +ardour_ui.cc +ardour_ui2.cc +ardour_ui_dialogs.cc +audio_time_axis.cc +automation_line.c +canvas-imageframe.cc +about.cc +editor.cc +editor_edit_groups.cc +editor_imageframe.cc +editor_keyboard.cc +editor_mouse.cc +editor_ops.cc +editor_region_list.cc +editor_route_list.cc +editor_rulers.cc +editor_selection_list.cc +export_dialog.cc +gain_meter.cc +io_selector.cc +library_ui.cc +meter_bridge.cc +mixer_strip.cc +mixer_ui.cc +new_session_dialog.cc +option_editor.cc +panner_ui.cc +playlist_selector.cc +plugin_selector.cc +plugin_ui.cc +redirect_box.cc +regionview.cc +route_params_ui.cc +""") + +extra_sources = [] +vst_files = [ 'vst_pluginui.cc' ] + +if env['VST']: + extra_sources += vst_files + +gtkardour.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE") +gtkardour.Append(CXXFLAGS="-DDATA_DIR=\\\""+final_prefix+"/share\\\"") +gtkardour.Append(CXXFLAGS="-DLOCALEDIR=\\\""+final_prefix+"/share/locale\\\"") + +versionflag = '-DVERSIONSTRING=\\\"' + env['VERSION'] + '\\\"' + +gtkardour.Append(CXXFLAGS=versionflag) + +gtkardour.VersionBuild(['version.cc','version.h'], 'SConscript') + +executable = 'ardour.bin' + +ardour = gtkardour.Program(target = executable, source = gtkardour_files + extra_sources) + +Default(ardour) + +if env['VERSIONED']: + Default (env.VersionedExecutable ('tagged_executable', ardour)) + +if env['NLS']: + i18n (gtkardour, gtkardour_files + extra_sources, env) + +#install + + +env.Alias('install', env.InstallAs(os.path.join(install_prefix, 'bin')+'/ardour', ardour)) +env.Alias('install', env.Install(os.path.join(config_prefix, 'ardour'), 'ardour_ui.rc')) +env.Alias('install', env.Install(os.path.join(install_prefix, 'share/ardour'), 'splash.ppm')) + +#dist +env.Alias ('tarball', env.Distribute (env['DISTTREE'], + [ 'SConscript', + 'i18n.h', 'gettext.h', + 'editor_xpms', 'misc_xpms', 'transport_xpms', + 'ardour_ui.rc', 'splash.ppm' + ] + + gtkardour_files + vst_files + + glob.glob('po/*.po') + glob.glob('*.h'))) + +# generate a prototype full-featured ardour_ui.rc file + +env.Alias ('protorc', env.Command ('proto.rc', gtkardour_files, """ + grep set_name $SOURCES | \ +sed 's/.*("\([a-zA-Z_][a-zA-Z_]*\)").*/\\1/' | \ +grep -v '\\.' | sort | uniq | \ +awk '/\\./ {} { printf ("style \\"%s\\"\\n{\\n\ + fg[NORMAL] = { 0, 0, 0 }\\n\ + fg[ACTIVE] = { 0, 0, 0 }\\n\ + fg[SELECTED] = { 0, 0, 0 }\\n\ + bg[NORMAL] = { 0, 0, 0 }\\n\ + bg[ACTIVE] = { 0, 0, 0 }\\n\ + bg[SELECTED] = { 0, 0, 0 }\\n\ +}\\nwidget \\"*%s\\" style \\"%s\\"\\nwidget \\"*%s*\\" style \\"%s\\"\\n\\n", \ + $$0, $$0, $$0, $$0, $$0) }' > $TARGET && \ + grep 'color_map\[[a-zA-Z_][a-zA-Z]*\]' $SOURCES | \ + sed 's/.*\[\([a-zA-Z_][a-zA-Z_]*\)].*/\\1/'| \ + sort | uniq | \ + awk '{ printf ("style \\"%s\\"\\n{\\n\ + fg[NORMAL] = { 0, 0, 0 }\\n\ + fg[ACTIVE] = { 0, 0, 0 }\\n\ +}\\nwidget \\"*%s\\" style \\"%s\\"\\n \\n\\n", $$0, $$0, $$0) }' >> $TARGET ; +""" +)) diff --git a/gtk2_ardour/ab.xpm b/gtk2_ardour/ab.xpm new file mode 100644 index 0000000000..7496178e78 --- /dev/null +++ b/gtk2_ardour/ab.xpm @@ -0,0 +1,648 @@ +/* XPM */ +static const gchar * about_xpm[] = { +"256 256 389 2", +" c None", +". c #DF94BA", +"+ c #DE94BA", +"@ c #DD94BB", +"# c #DC94BB", +"$ c #DB94BC", +"% c #DA94BC", +"& c #D994BC", +"* c #D894BD", +"= c #D794BD", +"- c #D694BE", +"; c #D594BE", +"> c #D494BF", +", c #D394BF", +"' c #D294BF", +") c #D194C0", +"! c #D094C0", +"~ c #CF94C1", +"{ c #CE94C1", +"] c #CD94C1", +"^ c #CD95C2", +"/ c #CC95C2", +"( c #CB95C3", +"_ c #CA95C3", +": c #C995C3", +"< c #C895C4", +"[ c #C795C4", +"} c #C695C5", +"| c #C595C5", +"1 c #C495C6", +"2 c #C395C6", +"3 c #9F7EC4", +"4 c #8C72C4", +"5 c #C295C6", +"6 c #554EC1", +"7 c #1E2BBF", +"8 c #C195C7", +"9 c #544EC2", +"0 c #C095C7", +"a c #8A72C4", +"b c #C095C8", +"c c #BF95C8", +"d c #8972C5", +"e c #BE95C8", +"f c #534EC2", +"g c #BD95C9", +"h c #8872C6", +"i c #BC95C9", +"j c #8772C6", +"k c #BB95CA", +"l c #524EC3", +"m c #BA95CA", +"n c #BA96CA", +"o c #8672C6", +"p c #524FC3", +"q c #B996CA", +"r c #8572C6", +"s c #B896CB", +"t c #8572C7", +"u c #514FC3", +"v c #B796CB", +"w c #8472C7", +"x c #B696CC", +"y c #8372C8", +"z c #B596CC", +"A c #504FC3", +"B c #7267C6", +"C c #A48ACB", +"D c #947FC9", +"E c #AB89C8", +"F c #A88AC9", +"G c #7467C6", +"H c #4043C2", +"I c #625BC5", +"J c #655AC3", +"K c #AA89C9", +"L c #645BC4", +"M c #8272C8", +"N c #B496CD", +"O c #2F37C1", +"P c #504FC4", +"Q c #A989C9", +"R c #3037C0", +"S c #997EC7", +"T c #B396CD", +"U c #927FCA", +"V c #8172C8", +"W c #7167C7", +"X c #A38ACB", +"Y c #3F43C2", +"Z c #B296CD", +"` c #4F4FC4", +" . c #A28ACB", +".. c #A28ACC", +"+. c #B296CE", +"@. c #927FCB", +"#. c #7067C7", +"$. c #8172C9", +"%. c #605BC6", +"&. c #B196CE", +"*. c #635BC4", +"=. c #8072C9", +"-. c #A18ACC", +";. c #B096CE", +">. c #4143C1", +",. c #4243C1", +"'. c #7F72C9", +"). c #A08ACC", +"!. c #6F67C7", +"~. c #5F5BC6", +"{. c #B096CF", +"]. c #AC89C8", +"^. c #A08ACD", +"/. c #3F43C3", +"(. c #7F72CA", +"_. c #907FCB", +":. c #6F67C8", +"<. c #AF96CF", +"[. c #967FC8", +"}. c #4E4FC4", +"|. c #8F7FCB", +"1. c #3E43C3", +"2. c #9F8ACD", +"3. c #AE96CF", +"4. c #7E72CA", +"5. c #6E67C8", +"6. c #2E37C1", +"7. c #9E8ACD", +"8. c #AD96D0", +"9. c #7D72CA", +"0. c #4E4FC5", +"a. c #5E5BC7", +"b. c #AC96D0", +"c. c #4D4FC5", +"d. c #8D7FCC", +"e. c #9C8ACE", +"f. c #AB96D0", +"g. c #7C72CA", +"h. c #8C7FCC", +"i. c #AB96D1", +"j. c #7C72CB", +"k. c #AA96D1", +"l. c #7B72CB", +"m. c #3D43C3", +"n. c #6C67C9", +"o. c #A78ACA", +"p. c #7367C6", +"q. c #2F37C0", +"r. c #977FC8", +"s. c #A996D2", +"t. c #4C4FC5", +"u. c #7B72CC", +"v. c #A896D2", +"w. c #7A72CC", +"x. c #A58ACB", +"y. c #A797D2", +"z. c #7973CC", +"A. c #957FC8", +"B. c #A697D3", +"C. c #4B4FC6", +"D. c #5B5BC8", +"E. c #A597D3", +"F. c #7873CC", +"G. c #2D37C1", +"H. c #6967CA", +"I. c #A497D4", +"J. c #7773CD", +"K. c #958BD2", +"L. c #9B7EC6", +"M. c #877FCF", +"N. c #A397D4", +"O. c #4A4FC6", +"P. c #3C43C4", +"Q. c #6867CB", +"R. c #A297D5", +"S. c #7673CE", +"T. c #595BC9", +"U. c #2D37C2", +"V. c #A197D5", +"W. c #7573CE", +"X. c #847FD0", +"Y. c #978BD1", +"Z. c #3B43C4", +"`. c #938BD3", +" + c #A097D5", +".+ c #968BD1", +"++ c #6D67C8", +"@+ c #6667CB", +"#+ c #494FC6", +"$+ c #928BD3", +"%+ c #837FD0", +"&+ c #585BC9", +"*+ c #5A5BC8", +"=+ c #605BC5", +"-+ c #9F97D6", +";+ c #837FD1", +">+ c #6667CC", +",+ c #7473CE", +"'+ c #494FC7", +")+ c #918BD3", +"!+ c #6767CB", +"~+ c #3C43C3", +"{+ c #9A8AD0", +"]+ c #5C5BC7", +"^+ c #8E7FCB", +"/+ c #9E97D6", +"(+ c #6567CC", +"_+ c #908BD3", +":+ c #7373CE", +"<+ c #987FC8", +"[+ c #8E7FCC", +"}+ c #575BC9", +"|+ c #9D97D7", +"1+ c #595BC8", +"2+ c #867FCF", +"3+ c #997EC8", +"4+ c #817FD2", +"5+ c #7373CF", +"6+ c #8F8BD4", +"7+ c #9C97D7", +"8+ c #9B97D8", +"9+ c #9A97D8", +"0+ c #9997D8", +"a+ c #9997D9", +"b+ c #9897D9", +"c+ c #9797D9", +"d+ c #9797DA", +"e+ c #9697DA", +"f+ c #6E73D1", +"g+ c #7273CF", +"h+ c #7173D0", +"i+ c #898BD7", +"j+ c #3943C5", +"k+ c #545BCB", +"l+ c #6167CD", +"m+ c #464FC8", +"n+ c #2C37C2", +"o+ c #9597DA", +"p+ c #9D8ACE", +"q+ c #484FC7", +"r+ c #555BCA", +"s+ c #6D73D1", +"t+ c #6167CE", +"u+ c #7C7FD3", +"v+ c #9C8ACF", +"w+ c #948BD2", +"x+ c #7F7FD3", +"y+ c #7073D0", +"z+ c #6F73D0", +"A+ c #7C7FD4", +"B+ c #6067CE", +"C+ c #888BD7", +"D+ c #8B8BD6", +"E+ c #8E8BD4", +"F+ c #6A67CA", +"G+ c #8C7FCD", +"H+ c #474FC7", +"I+ c #6F73D1", +"J+ c #7B7FD4", +"K+ c #8A8BD7", +"L+ c #6267CD", +"M+ c #6367CD", +"N+ c #3A43C5", +"O+ c #615BC5", +"P+ c #9B8ACF", +"Q+ c #827FD1", +"R+ c #7D7FD3", +"S+ c #857FD0", +"T+ c #6967CB", +"U+ c #937FCA", +"V+ c #7566C5", +"W+ c #917FCB", +"X+ c #555BCB", +"Y+ c #5D5BC7", +"Z+ c #7E7FD3", +"`+ c #535BCB", +" @ c #474FC8", +".@ c #6467CC", +"+@ c #7467C5", +"@@ c #957FC9", +"#@ c #645AC4", +"$@ c #7567C5", +"%@ c #5B5BC7", +"&@ c #565BCA", +"*@ c #8C8BD5", +"=@ c #8A8BD6", +"-@ c #887FCF", +";@ c #807FD3", +">@ c #3A43C4", +",@ c #8B7FCD", +"'@ c #7267C7", +")@ c #998AD0", +"!@ c #6B67CA", +"~@ c #807FD2", +"{@ c #8B8BD5", +"]@ c #8A7FCE", +"^@ c #6467CD", +"/@ c #988BD0", +"(@ c #8D8BD5", +"_@ c #575BCA", +":@ c #9358B7", +"<@ c #700999", +"[@ c #A587CA", +"}@ c #9058B8", +"|@ c #A487CB", +"1@ c #8A48B2", +"2@ c #77199F", +"3@ c #8338AC", +"4@ c #9967BE", +"5@ c #9E77C5", +"6@ c #8438AC", +"7@ c #9767BE", +"8@ c #A587CB", +"9@ c #8438AB", +"0@ c #7D29A5", +"a@ c #9158B8", +"b@ c #7E29A5", +"c@ c #8B48B2", +"d@ c #9F77C4", +"e@ c #9867BE", +"f@ c #A077C4", +"g@ c #9D67BC", +"h@ c #9C67BC", +"i@ c #A477C2", +"j@ c #A687CA", +"k@ c #A067BA", +"l@ c #B187C5", +"m@ c #9E67BB", +"n@ c #78199F", +"o@ c #8638AA", +"p@ c #8638AB", +"q@ c #9967BD", +"r@ c #8C48B1", +"s@ c #8538AB", +"t@ c #A787C9", +"u@ c #A077C3", +"v@ c #A377C2", +"w@ c #8F48B0", +"x@ c #8029A4", +"y@ c #8838AA", +"z@ c #9957B4", +"A@ c #A677C1", +"B@ c #7F29A5", +"C@ c #9A67BD", +"D@ c #A887C9", +"E@ c #A177C3", +"F@ c #8738AA", +"G@ c #B386C5", +"H@ c #7F29A4", +"I@ c #A987C9", +"J@ c #9B67BD", +"K@ c #9458B7", +"L@ c #8D48B1", +"M@ c #A277C3", +"N@ c #9B67BC", +"O@ c #A777C1", +"P@ c #A266BA", +"Q@ c #9658B6", +"R@ c #A277C2", +"S@ c #A987C8", +"T@ c #AC87C7", +"U@ c #A577C2", +"V@ c #AA87C8", +"W@ c #AB76BF", +"X@ c #9658B5", +"Y@ c #9558B7", +"Z@ c #AB87C8", +"`@ c #8E48B1", +" # c #8838A9", +".# c #8938A9", +"+# c #9558B6", +"@# c #8E48B0", +"## c #AB87C7", +"$# c #AD87C7", +"%# c #9F67BA", +"&# c #AD87C6", +"*# c #9858B5", +"=# c #AE87C6", +"-# c #9758B5", +";# c #9F67BB", +"># c #9048AF", +",# c #AF87C6", +"'# c #A777C0", +")# c #A977BF", +"!# c #A877C0", +"~# c #9958B4", +"{# c #A167BA", +"]# c #AA76BF", +"^# c #B286C5", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + ", +". + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @ + ", +". + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ # @ + ", +". + @ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # $ # @ + ", +". + @ # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % $ # @ + ", +". + @ # $ % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % & % $ # @ + ", +". + @ # $ % & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & * & % $ # @ + ", +". + @ # $ % & * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * = * & % $ # @ + ", +". + @ # $ % & * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = - = * & % $ # @ + ", +". + @ # $ % & * = - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 4 4 4 4 4 4 4 4 4 4 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 6 7 7 7 7 7 7 7 7 7 7 6 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 9 7 7 7 7 7 7 7 7 7 7 9 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 a 7 7 7 7 7 7 7 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b 9 7 7 7 7 7 7 9 b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c d 7 7 7 7 7 7 9 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e d 7 7 7 7 7 7 f e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g h 7 7 7 7 7 7 f g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i j 7 7 7 7 7 7 f i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i j 7 7 7 7 7 7 f i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k j 7 7 7 7 7 7 l k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n o 7 7 7 7 7 7 p n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n n q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q r 7 7 7 7 7 7 p q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s t 7 7 7 7 7 7 u s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s t 7 7 7 7 7 7 u s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v w 7 7 7 7 7 7 u v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x y 7 7 7 7 7 7 u x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v y y A A A A A B y z z z z z z z z z z z z z z z z z z z z z z z z z z z z z C y A A A y z z z z z z z z z z z z z z y y A A A A A y y D y 7 7 7 7 7 7 A z z z z z z z z z z z z z z z z z z y B A A A A B y z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z z x v s s q m k i E h f 9 9 a 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n F G H 7 7 7 7 7 7 7 7 7 7 7 A D z z z z z z z z z 7 7 7 7 7 7 7 7 7 7 7 y z z z z I 7 7 7 7 7 A z z z z z z z z z z z D A 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 A z z z z z z z z z z z z z z z D H 7 7 7 7 7 7 7 7 7 7 H D z z z z z z z z z z z A 7 7 7 7 7 7 7 7 7 7 A z z z z z z z A 7 7 7 7 7 7 7 7 7 7 A z z z z z z 7 7 7 7 7 7 7 7 7 7 7 t s q m k J 7 7 7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i K L 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 M N N N N N N N N 7 7 7 7 7 7 7 7 7 7 7 M N N C O 7 7 7 7 7 7 P N N N N N N N N N C P 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 P N N N N N N N N N N N N N C H 7 7 7 7 7 O P P O 7 7 7 7 7 H C N N N N N N N N N P 7 7 7 7 7 7 7 7 7 7 P N N N N N N N P 7 7 7 7 7 7 7 7 7 7 P N N N N N N 7 7 7 7 7 7 7 7 7 7 7 t s q Q R 7 7 7 7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i S 7 7 7 7 7 7 I D z N T U P 7 7 7 7 7 7 V T T T T T T T V V W O 7 7 7 7 7 7 7 V T X O 7 7 7 7 7 7 7 P T T T T T T T T U O 7 7 7 7 7 7 Y V X T T T V W Y 7 7 7 7 7 7 P T T T T T T T T T T T T V 7 7 7 7 7 O U T T T T U O 7 7 7 7 7 V T T T T T T T T U V V Y 7 7 7 7 7 7 7 P T T T T T T T U V V Y 7 7 7 7 7 7 7 P T T T T T T V V W O 7 7 7 7 7 7 7 t s F R 7 7 7 7 7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i j 7 7 7 7 7 w x z z N T Z Z ` 7 7 7 7 7 O Z Z Z Z Z Z Z Z Z Z .7 7 7 7 7 7 7 V Z O 7 7 7 7 7 7 7 7 ` Z Z Z Z Z Z Z V 7 7 7 7 7 7 O V Z Z Z Z Z Z Z Z V 7 7 7 7 7 7 ` Z Z Z Z Z Z Z Z Z Z Z V 7 7 7 7 7 O .Z Z Z Z Z Z .O 7 7 7 7 7 V Z Z Z Z Z Z Z Z Z Z Z Y 7 7 7 7 7 7 ` Z Z Z Z Z Z Z Z Z Z Z Y 7 7 7 7 7 7 ` Z Z Z Z Z Z Z Z Z ..7 7 7 7 7 7 7 t s R 7 7 7 7 7 7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i j 7 7 7 7 H v x z z N T Z +.@.7 7 7 7 7 7 #.+.+.+.+.+.+.+.+.+.+.Y 7 7 7 7 7 7 $.%.7 7 7 7 7 7 7 7 7 ` +.+.+.+.+.+...O 7 7 7 7 7 O ..+.+.+.+.+.+.+.+.+.$.7 7 7 7 7 7 ` +.+.+.+.+.+.+.+.+.+.$.7 7 7 7 7 O ..+.+.+.+.+.+.+.+...7 7 7 7 7 7 @.+.+.+.+.+.+.+.+.+.+.#.7 7 7 7 7 7 ` +.+.+.+.+.+.+.+.+.+.+.#.7 7 7 7 7 7 ` +.+.+.+.+.+.+.+.&.+.Y 7 7 7 7 7 7 t *.7 7 7 7 7 7 7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i j 7 7 7 7 *.v x z z N T Z +.&.7 7 7 7 7 7 ` &.&.&.&.&.&.&.&.&.&.` 7 7 7 7 7 7 %.7 7 7 Y =.=.Y 7 7 7 ` &.&.&.&.&.&.O 7 7 7 7 7 7 -.&.&.&.&.&.&.&.&.&.&.=.7 7 7 7 7 7 ` &.&.&.&.&.&.&.&.&.-.O 7 7 7 7 7 #.&.&.&.&.&.&.&.&.&.&.#.7 7 7 7 7 O -.&.&.&.&.&.&.&.&.&.=.7 7 7 7 7 7 ` &.&.&.&.&.&.&.&.&.&.&.=.7 7 7 7 7 7 ` &.&.&.&.&.&.&.;.&.+.` 7 7 7 7 7 7 *.7 7 7 >.j j ,.7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i j 7 7 7 7 t v x z z N T Z +.&.7 7 7 7 7 7 7 ;.;.;.;.;.;.;.;.;.;.` 7 7 7 7 7 7 7 7 O '.;.;.;.).7 7 7 ` ;.;.;.;.;.!.7 7 7 7 7 7 !.;.;.;.;.;.;.;.;.;.;.;.'.7 7 7 7 7 7 ` ;.;.;.;.;.;.;.;.;.` 7 7 7 7 7 O ;.;.;.;.;.;.;.;.;.;.;.;.O 7 7 7 7 7 ~.;.;.;.;.;.;.;.;.;.'.7 7 7 7 7 7 ` ;.;.;.;.;.;.;.;.;.;.;.'.7 7 7 7 7 7 ` ;.;.;.;.;.;.{.;.&.+.` 7 7 7 7 7 7 7 7 R o k i i ].7 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i j 7 7 7 7 t v x z z N T Z +.&.` 7 7 7 7 7 7 ^.{.{.{.{.{.{.{.{.{.` 7 7 7 7 7 7 7 O ^.{.{.{.{.{./.7 7 ` {.{.{.{.^.7 7 7 7 7 7 O {.{.{.{.{.{.{.{.{.{.{.{.(.7 7 7 7 7 7 ` {.{.{.{.{.{.{.{._.7 7 7 7 7 7 :.{.{.{.{.{.{.{.{.{.{.{.{.:.7 7 7 7 7 7 _.{.{.{.{.{.{.{.{.(.7 7 7 7 7 7 ` {.{.{.{.{.{.{.{.{.{.{.(.7 7 7 7 7 7 ` {.{.{.{.{.<.{.;.&.+.` 7 7 7 7 7 7 7 R F m k i i g ,.7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i S l p p u [.v x z z N T Z +.&.` 7 7 7 7 7 7 (.<.<.<.<.<.<.<.<.<.}.7 7 7 7 7 7 7 |.<.<.<.<.<.<.}.7 7 }.<.<.<.<.~.7 7 7 7 7 7 :.<.<.<.<.<.<.<.<.<.<.<.<.(.7 7 7 7 7 7 }.<.<.<.<.<.<.<.<.1.7 7 7 7 7 7 2.<.<.<.<.<.<.<.<.<.<.<.<.2.7 7 7 7 7 7 }.<.<.<.<.<.<.<.<.(.7 7 7 7 7 7 }.<.<.<.<.<.<.<.<.<.<.<.(.7 7 7 7 7 7 }.<.<.<.<.3.<.{.;.&.+.` 7 7 7 7 7 7 7 [.q m k i i g f 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.` 7 7 7 7 7 7 4.3.3.3.3.3.3.3.3.3.}.7 7 7 7 7 7 5.3.3.3.3.3.3.3.}.7 7 }.3.3.3.3.6.7 7 7 7 7 7 3.3.3.3.3.3.3.3.3.3.3.3.3.4.7 7 7 7 7 7 }.3.3.3.3.3.3.3.7.7 7 7 7 7 7 1.3.3.3.3.3.3.3.3.3.3.3.3.3.3.1.7 7 7 7 7 7 7.3.3.3.3.3.3.3.4.7 7 7 7 7 7 }.3.3.3.3.3.3.3.3.3.3.3.4.7 7 7 7 7 7 }.3.3.3.8.3.<.{.;.&.+.` 7 7 7 7 7 7 G s q m k i i g f 7 7 9 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.` 7 7 7 7 7 7 9.8.8.8.8.8.8.8.8.8.0.7 7 7 7 7 7 9.8.8.8.8.8.8.8.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.8.8.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.8.8.8.5.7 7 7 7 7 7 a.8.8.8.8.8.8.8.8.8.8.8.8.8.8.a.7 7 7 7 7 7 5.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.` 7 7 7 7 7 7 9.8.8.8.8.8.8.8.8.8.0.7 7 7 7 7 7 9.8.8.8.8.8.8.8.8.8.8.8.8.8.8.a.7 7 7 7 7 7 5.8.8.8.8.8.8.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.8.8.8.0.7 7 7 7 7 7 9.8.8.8.8.8.8.8.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.8.8.8.8.8.8.8.8.8.8.9.7 7 7 7 7 7 0.8.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.` 7 7 7 7 7 7 9.b.b.b.b.b.b.b.b.b.c.7 7 7 7 7 7 9.b.b.b.b.b.b.b.b.b.b.b.b.b.b.6.7 7 7 7 7 7 d.b.b.b.b.b.b.b.b.b.b.b.b.b.9.7 7 7 7 7 7 c.b.b.b.b.b.b.b.7 7 7 7 7 7 7 e.b.b.b.b.b.b.b.b.b.b.b.b.b.b.d.7 7 7 7 7 7 7 b.b.b.b.b.b.b.9.7 7 7 7 7 7 c.b.b.b.b.b.b.b.b.b.b.b.9.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.` 7 7 7 7 7 7 g.f.f.f.f.f.f.f.f.f.c.7 7 7 7 7 7 g.f.f.f.f.f.f.f.f.f.f.f.f.f.f.7 7 7 7 7 7 7 f.f.f.f.f.f.f.f.f.f.f.f.f.f.g.7 7 7 7 7 7 c.f.f.f.f.f.f.h.7 7 7 7 7 7 7 f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.7 7 7 7 7 7 7 h.f.f.f.f.f.f.g.7 7 7 7 7 7 c.f.f.f.f.f.f.f.f.f.f.f.g.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.i.i.i.i.i.i.i.i.c.7 7 7 7 7 7 j.i.i.i.i.i.i.i.i.i.i.i.i.i.j.7 7 7 7 7 7 7 i.i.i.i.i.i.i.i.i.i.i.i.i.i.j.7 7 7 7 7 7 c.i.i.i.i.i.i.j.7 7 7 7 7 7 7 i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.7 7 7 7 7 7 7 j.i.i.i.i.i.i.j.7 7 7 7 7 7 c.i.i.i.i.i.i.i.i.i.i.i.j.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z C V V $.=.Y 7 7 7 7 7 7 g.i.k.k.k.k.k.k.k.k.c.7 7 7 7 7 7 l.k.k.k.k.k.k.k.k.k.k.k.k.k.l.7 7 7 7 7 7 m.k.k.k.k.k.k.k.k.k.k.k.k.k.k.l.7 7 7 7 7 7 c.k.k.k.k.k.k.n.7 7 7 7 7 7 m.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.m.7 7 7 7 7 7 l.k.k.k.k.k.k.l.7 7 7 7 7 7 c.k.k.k.k.k.k.k.k.k.k.k.l.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s o.p.u q.7 7 7 7 7 7 7 7 7 7 7 7 7 g.i.k.k.k.k.k.k.k.k.c.7 7 7 7 7 7 l.k.k.k.k.k.k.k.k.k.k.k.k.k.n.7 7 7 7 7 7 c.k.k.k.k.k.k.k.k.k.k.k.k.k.k.l.7 7 7 7 7 7 c.k.k.k.k.k.k.c.7 7 7 7 7 7 c.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.c.7 7 7 7 7 7 c.k.k.k.k.k.k.l.7 7 7 7 7 7 c.k.k.k.k.k.k.k.k.k.k.k.l.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r.H 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 g.i.k.k.s.s.s.s.s.s.t.7 7 7 7 7 7 u.s.s.s.s.s.s.s.s.s.s.s.s.s.t.7 7 7 7 7 7 t.s.s.s.s.s.s.s.s.s.s.s.s.s.s.u.7 7 7 7 7 7 t.s.s.s.s.s.s.t.7 7 7 7 7 7 t.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.t.7 7 7 7 7 7 t.s.s.s.s.s.s.u.7 7 7 7 7 7 t.s.s.s.s.s.s.s.s.s.s.s.u.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k p 7 7 7 7 7 7 I M T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.v.v.v.t.7 7 7 7 7 7 w.v.v.v.v.v.v.v.v.v.v.v.v.v.t.7 7 7 7 7 7 t.v.v.v.v.v.v.v.v.v.v.v.v.v.v.w.7 7 7 7 7 7 t.v.v.v.v.v.v.t.7 7 7 7 7 7 t.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.t.7 7 7 7 7 7 t.v.v.v.v.v.v.w.7 7 7 7 7 7 t.v.v.v.v.v.v.v.v.v.v.v.w.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i E R 7 7 7 7 7 q.C z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.v.v.v.t.7 7 7 7 7 7 w.v.v.v.v.v.v.v.v.v.v.v.v.v.t.7 7 7 7 7 7 t.v.v.v.v.v.v.v.v.v.v.v.v.v.v.w.7 7 7 7 7 7 t.v.v.v.v.v.v.t.7 7 7 7 7 7 t.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.t.7 7 7 7 7 7 t.v.v.v.v.v.v.w.7 7 7 7 7 7 t.v.v.v.v.v.v.v.v.v.v.v.w.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i R 7 7 7 7 7 q.x.z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.y.y.t.7 7 7 7 7 7 z.y.y.y.y.y.y.y.y.y.y.y.y.y.t.7 7 7 7 7 7 t.y.y.y.y.y.y.y.y.y.y.y.y.y.y.z.7 7 7 7 7 7 t.y.y.y.y.y.y.t.7 7 7 7 7 7 t.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.t.7 7 7 7 7 7 t.y.y.y.y.y.y.z.7 7 7 7 7 7 t.y.y.y.y.y.y.y.y.y.y.y.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g J 7 7 7 7 7 7 A.x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 z.B.B.B.B.B.B.B.B.B.B.B.B.B.C.7 7 7 7 7 7 C.B.B.B.B.B.B.B.B.B.B.B.B.B.B.z.7 7 7 7 7 7 C.B.B.B.B.B.B.C.7 7 7 7 7 7 C.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.C.7 7 7 7 7 7 C.B.B.B.B.B.B.z.7 7 7 7 7 7 C.B.B.B.B.B.B.B.B.B.B.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e ].7 7 7 7 7 7 H v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 z.B.B.B.B.B.B.B.B.B.B.B.B.B.C.7 7 7 7 7 7 C.B.B.B.B.B.B.B.B.B.B.B.B.B.B.z.7 7 7 7 7 7 C.B.B.B.B.B.B.D.7 7 7 7 7 7 C.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.C.7 7 7 7 7 7 D.B.B.B.B.B.B.z.7 7 7 7 7 7 C.B.B.B.B.B.B.B.B.B.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e J 7 7 7 7 7 7 G v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 F.E.E.E.E.E.E.E.E.E.E.E.E.E.C.7 7 7 7 7 7 G.E.E.E.E.E.E.E.E.E.E.E.E.E.E.F.7 7 7 7 7 7 C.E.E.E.E.E.E.F.7 7 7 7 7 7 C.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.G.7 7 7 7 7 7 F.E.E.E.E.E.E.F.7 7 7 7 7 7 C.E.E.E.E.E.E.E.E.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e ,.7 7 7 7 7 7 t v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 F.E.E.E.E.E.E.E.E.E.E.E.E.E.H.7 7 7 7 7 7 7 E.E.E.E.E.E.E.E.E.E.E.E.E.E.F.7 7 7 7 7 7 C.E.E.E.E.E.E.F.7 7 7 7 7 7 G.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.7 7 7 7 7 7 7 F.E.E.E.E.E.E.F.7 7 7 7 7 7 C.E.E.E.E.E.E.E.I.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e 7 7 7 7 7 7 7 s v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 J.I.I.I.I.I.I.I.I.I.I.I.I.I.J.7 7 7 7 7 7 7 I.I.I.I.I.I.I.I.I.I.I.I.I.I.J.7 7 7 7 7 7 C.I.I.I.I.I.I.K.7 7 7 7 7 7 7 I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.7 7 7 7 7 7 7 K.I.I.I.I.I.I.J.7 7 7 7 7 7 C.I.I.I.I.I.I.I.I.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c L.7 7 7 7 7 7 7 s v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 J.I.I.I.I.I.I.I.I.I.I.I.I.I.J.7 7 7 7 7 7 7 M.I.I.I.I.I.I.I.I.I.I.I.I.I.J.7 7 7 7 7 7 C.I.I.I.I.I.I.I.G.7 7 7 7 7 7 I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.J.7 7 7 7 7 7 G.I.I.I.I.I.I.I.J.7 7 7 7 7 7 C.I.I.I.I.I.N.I.I.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c d 7 7 7 7 7 7 7 s v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 J.N.N.N.N.N.N.N.N.N.N.N.N.N.N.7 7 7 7 7 7 7 J.N.N.N.N.N.N.N.N.N.N.N.N.N.J.7 7 7 7 7 7 O.N.N.N.N.N.N.N.O.7 7 7 7 7 7 J.N.N.N.N.N.N.N.N.N.N.N.N.N.N.J.7 7 7 7 7 7 O.N.N.N.N.N.N.N.J.7 7 7 7 7 7 O.N.N.N.N.N.N.I.I.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c d 7 7 7 7 7 7 7 s v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 J.N.N.N.N.N.N.N.N.N.N.N.N.N.N.P.7 7 7 7 7 7 O.N.N.N.N.N.N.N.N.N.N.N.N.N.J.7 7 7 7 7 7 O.N.N.N.N.N.N.N.J.7 7 7 7 7 7 Q.N.N.N.N.N.N.N.N.N.N.N.N.N.N.O.7 7 7 7 7 7 J.N.N.N.N.N.N.N.J.7 7 7 7 7 7 O.N.N.N.R.N.N.I.I.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c d 7 7 7 7 7 7 7 s v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 S.R.R.R.R.R.R.R.R.R.R.R.R.R.R.T.7 7 7 7 7 7 7 R.R.R.R.R.R.R.R.R.R.R.R.R.Q.7 7 7 7 7 7 O.R.R.R.R.R.R.R.R.U.7 7 7 7 7 O.R.R.R.R.R.R.R.R.R.R.R.R.R.R.U.7 7 7 7 7 7 R.R.R.R.R.R.R.R.S.7 7 7 7 7 7 O.R.R.V.R.N.N.I.I.E.E.B.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c d 7 7 7 7 7 7 7 t v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 W.V.V.V.V.V.V.V.V.V.V.V.V.V.V.X.7 7 7 7 7 7 7 W.V.V.V.V.V.V.V.V.V.V.V.W.7 7 7 7 7 7 7 O.V.V.V.V.V.V.V.V.T.7 7 7 7 7 7 V.V.V.V.V.V.V.V.V.V.V.V.V.X.7 7 7 7 7 7 T.V.V.V.V.V.V.V.V.X.7 7 7 7 7 7 U.V.V.V.R.N.N.I.I.E.E.Y.G.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e 7 7 7 7 7 7 7 *.v x z z N T Z +.&.` 7 7 7 7 7 7 g.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 W.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.U.7 7 7 7 7 7 Z.V.V.V.V.V.V.V.V.V.V.W.7 7 7 7 7 7 7 7 O.V.V.V.V.V.V.V.V.`.U.7 7 7 7 7 W.V.V.V.V.V.V.V.V.V.V.V.V.T.7 7 7 7 7 7 `.V.V.V.V.V.V.V.V.V.7 7 7 7 7 7 7 +V.V.R.N.N.I.I.E..+G.7 7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e R 7 7 7 7 7 7 R v x z z N T Z +.-.O 7 7 7 7 7 7 ++i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 W.V. + + + + + + + + + + + + + +@+7 7 7 7 7 7 7 @+ + + + + + + + +W.7 7 #+7 7 7 7 7 7 #+ + + + + + + + + +@+7 7 7 7 7 Z. + + + + + + + + + + +$+7 7 7 7 7 7 @+ + + + + + + + + + +7 7 7 7 7 7 7 W.V.V.R.N.N.I.I.F.G.7 C.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e J 7 7 7 7 7 7 7 u x z z N T Z @.O 7 ` 7 7 7 7 7 c.i.k.k.s.v.v.y.B.B.C.7 7 7 7 7 7 W.V. + + + + + + + + + + + + + + +U.7 7 7 7 7 7 7 @+ + + + + +$+#+7 7 #+W.7 7 7 7 7 7 #+ + + + + + + + + + +Z.7 7 7 7 7 %+ + + + + + + + + + +&+7 7 7 7 7 Z. + + + + + + + + + + +#+7 7 7 7 7 7 U.V.V.R.N.N.K.*+7 7 C.z.7 7 7 7 7 7 c.f.b.8.8.3.<.{.;.&.+.` 7 7 7 7 7 7 t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e ].7 7 7 7 7 7 7 7 u D z N U =+7 7 O ^.}.7 7 7 7 1.i.k.k.s.v.v.y.B.B.7 7 7 7 7 7 7 O.V. + +-+-+-+-+-+-+-+-+-+-+-+-+-+;+7 7 7 7 7 7 7 7 Z.>+,+,+'+7 7 7 U.)+,+7 7 7 7 7 7 7 -+-+-+-+-+-+-+-+-+-+)+U.7 7 7 7 U.)+-+-+-+-+-+-+-+-+,+7 7 7 7 7 U.)+-+-+-+-+-+-+-+-+-+-+-+>+7 7 7 7 7 7 7 U.!+S.J.O.7 7 7 ~+B.z.7 7 7 7 7 7 7 f.b.8.8.3.<.{.;.&.+.7 7 7 7 7 7 7 u s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g J 7 7 7 7 7 7 7 7 7 7 7 7 7 7 O ).{.(.7 7 7 7 7 j.k.k.{+v.v.y.Y.C.7 7 7 7 7 7 7 7 !+ + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+&+7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 )+-+,+7 7 7 7 7 7 7 '+)+-+-+-+-+-+-+-+-+-+)+U.7 7 7 7 U.)+-+-+-+-+-+-+,+7 7 7 7 7 U.)+-+-+-+-+-+-+-+-+-+-+-+-+)+7 7 7 7 7 7 7 7 7 7 7 7 7 7 G..+B.z.7 7 7 7 7 7 7 c.e.8.8.3.<.{.;.-.` 7 7 7 7 7 7 7 7 G q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i f 7 7 7 7 7 7 7 7 7 7 7 7 O -.;.{.<.6.7 7 7 7 7 7 7 ]+v.7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 '+-+-+-+-+-+-+-+-+-+-+-+-+-+-+'+7 7 7 7 7 7 7 7 7 7 7 7 U.,+-+-+,+7 7 7 7 7 7 7 7 7 7 7 -+-+-+-+-+-+-+-+)+Z.7 7 7 7 7 &+;+-+-+;+&+7 7 7 7 7 Z.)+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&+7 7 7 7 7 7 7 7 7 7 7 7 P..+E.B.z.7 7 7 7 7 7 7 7 7 7 7 3.<.7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 l i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i l 7 7 7 7 7 7 7 7 7 7 Y ..&.;.{.<.^+7 7 7 7 7 7 7 t.v.7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 '+-+-+/+/+/+/+/+/+/+/+/+/+/+/+/+(+7 7 7 7 7 7 7 7 7 7 U._+/+/+/+:+7 7 7 7 7 7 7 7 7 7 7 /+/+/+/+/+/+/+/+/+/+(+7 7 7 7 7 7 7 7 7 7 7 7 7 U.(+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+'+7 7 7 7 7 7 7 7 7 7 *+I.E.E.B.z.7 7 7 7 7 7 7 7 7 7 7 3.<.7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 l i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k <+>.7 7 7 7 7 7 H U Z +.&.;.{.<.3.[+6.7 7 7 7 m.u.v.w.z.z.z.F.F.J.J.J.J.S.W.W.W.W.;+-+-+/+/+/+/+/+/+/+/+/+/+/+/+/+/+_+}+7 7 7 7 7 7 Z.(+/+/+/+/+/+_+:+:+:+:+:+:+:+:+:+:+:+/+/+/+/+/+/+/+/+/+/+/+/+(+Z.7 7 7 7 7 7 7 7 '+:+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+/+|+/+/+>+U.7 7 7 7 7 7 1+2+I.I.E.E.B.Y.z.w.w.u.l.l.j.g.9.9.9.3.<.(.'.=.$.V V M y y y w t t r o 3+i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s t w y y z N T Z +.&.;.{.<.3.8.8.d.g.j.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+4+5+5+5+6+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+4+5+5+5+5+6+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+/+/+-+-+)+W.W.W.X.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+7+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+8+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+7 7 7 7 7 f+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.C.7 7 7 7 u.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i E j o r t t w y y y M V V @.&.;.{.<.3.8.8.b.f.i.k.k.u.w.w.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+g+g+h+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+i+j+7 7 f+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+k+l+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.Y.6.7 7 u.k.k.i.f.d.9.9.7.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i S l >.7 7 7 7 u A A O 7 7 7 7 Y (.<.3.8.8.b.f.i.k.k.7 7 7 y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+m+7 7 f+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+i+7 n+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n *.7 7 7 x z z N T U %.O 7 7 1.7.8.8.b.f.i.k.k.7 7 7 y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+m+7 7 f+e+e+e+e+e+e+e+e+e+e+e+e+e+e+o+e+e+e+e+e+k+7 7 l+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.-.` 7 7 6.p+8.b.f.i.k.k.t.t.t.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+q+q+q+8+9+9+9+0+r+j+7 b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+7 7 7 j+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.t.7 7 u.k.k.i.f.++0.0.^+<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.` 7 7 6.p+b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+7 7 7 b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+t+7 7 7 7 u+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.t.7 7 u.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.^.7 7 7 a.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+7 7 7 b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+j+k+n+7 7 k+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.t.7 7 u.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.~.7 7 7 e.f.v+l.l.u.w.w.y.B.B.E.E.I.I.w+Q.O.O.T.%+ +,+,+,+:+_+6+5+g+g+g+h+8+9+9+x+y+7 7 7 z+z+z+u+c+c+d+e+A+t+m+m+m+B+C+o+o+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+A+7 i+k+7 7 7 D+b+b+a+a+0+0+9+x+h+h+h+g+E+7+|+|+:+:+,+,+,+ + +V.V.R.N.N.K.J.C.C.C.F+m.7 7 u.k.k.j.g.9.9.9.7.<.{.;.&.+.Z T C B A u u t s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.|.7 7 7 ++f.G+c.6.7 7 7 y.B.B.E.E.I.J.7 7 Q.W.O.7 7 Z.7 7 7 _+4+q+n+7 7 7 8+9+9+H+7 7 7 7 7 7 7 m+c+c+I+n+7 n+m+m+n+7 n+J+o+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+m+m+e+K+7 7 7 L+b+b+a+a+0+0+9+M+N+7 7 7 g+7+|+|+'+U.7 7 7 + +V.V.R.N.Q.7 7 7 C.C.C.7 7 7 u.k.k.c.1.7 7 7 4.<.{.;.&.+.Z O+7 7 B y u 7 R r.m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.7 7 7 c.f.i.k.P+7 7 7 y.B.B.E.E.J.7 7 Q.R.V.V.Z.7 '+-+)+Q+/+|+|+E+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+m+7 n+i+e+e+i+7 7 n+o+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+i+7 A+e+d+m+7 7 n+b+b+a+a+0+0+9+9+9+N+7 7 g+7+|+|+/+_+7 7 7 + +V.V.R.1+7 7 G..+E.B.B.t.7 7 u.k.k.i.f.1.7 7 4.<.{.;.&.+.` 7 7 D z x v u 7 7 o k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.1.7 7 6.f.i.k.k.7 7 7 y.B.B.E.E.G.7 7 N.R.V.V.W.7 7 ;+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+m+7 m+e+e+e+e+j+7 7 C+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+k+j+e+e+d+u+7 7 7 R+b+a+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.V.S+7 7 G.K.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.$.7 7 O+z z x v s 7 7 R k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.}.7 7 7 f.i.k.k.7 7 7 y.B.B.E..+7 7 O.N.R.V.V.$+7 7 '+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+A+f+A+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+n+t+e+e+d+c+n+7 7 j+b+a+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.V.P.7 7 T+I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.O 7 7 U+z z x v s u 7 7 V+i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.}.7 7 7 f.i.k.k.7 7 7 y.B.B.E.F.7 7 O.N.R.V.V. +7 7 7 -+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+d+e+e+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+f+n+e+e+e+d+c+l+7 7 7 D+a+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.`.7 7 7 K.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.W+7 7 7 N z z x v s t 7 7 R i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.}.7 7 7 f.i.k.k.7 7 7 y.B.B.E.F.7 7 O.N.R.V.V. +7 7 7 -+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+d+e+e+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+j+k+e+e+e+d+c+c+7 7 7 X+a+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.W.7 7 G.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.=.7 7 Y N z z x v s [.7 7 7 i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.}.7 7 7 f.i.k.k.7 7 7 y.B.B.E.F.7 7 O.N.R.V.V. +7 7 U.-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+d+e+e+e+f+f+f+j+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+A+7 i+e+e+e+d+c+c+k+7 7 n+a+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.T.7 7 O.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.` 7 7 P N z z x v s s 7 7 7 j i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.1.7 7 1.f.i.k.k.7 7 7 y.B.B.E.E.7 7 P.N.R.V.V.%+7 7 '+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+d+f+j+7 n+m+m+n+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+k+j+e+e+e+e+d+c+c+u+7 7 7 y+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.O.7 7 O.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.` 7 7 P N z z x v s s 7 7 7 j i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.<.7 7 7 Y+f.i.k.k.7 7 7 y.B.B.E.E.*+7 7 w+R.V.V.@+7 7 )+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+c+m+7 7 m+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+7 j+m+m+m+m+m+m+m+m+7 7 7 j+a+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.O.7 7 O.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.` 7 7 P N z z x v s s 7 7 7 j i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.|.7 7 7 9.f.i.k.k.7 7 7 y.B.B.E.E.I.C.7 O.R.V.`.U.7 ,+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+z+7 7 j+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+B+n+m+m+m+m+m+m+m+m+m+j+7 7 7 Z+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.O.7 7 O.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.` 7 7 P N z z x v s s 7 7 7 j i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.:.7 7 6.b.f.i.k.k.7 7 7 y.B.B.E.E.I.I.Q.7 P.O.U.U.W.-+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+j+7 7 t+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+o+n+t+e+e+e+e+e+d+c+c+c+b+n+7 7 X+0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.O.7 7 O.I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.#.7 7 P N z z x v s o.7 7 7 E i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.{.6.7 7 5.b.f.i.k.k.7 7 7 y.B.B.E.E.I.K.G.O.S+W.W. + +-+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+7 7 7 f+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+J+7 e+e+e+e+e+e+d+c+c+c+b+L+7 7 7 0+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.W.7 7 7 I.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.=.7 7 O N z z x v s t 7 7 7 i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.;.~.7 7 1.8.b.f.i.k.k.7 7 7 y.B.B.E.E.K.G.7 w+R.V.V. + +-+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+7 7 7 b+b+b+c+c+7 7 7 f+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+o+j+`+e+e+e+e+e+e+d+c+c+c+b+D+7 7 7 L+0+9+9+9+q+7 7 g+7+|+|+/+/+7 7 7 + +V.X.7 7 7 K.I.E.E.B.B.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.7 7 7 N z z x v s *.7 7 l i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n r 7 7 7 x z z N T Z +.&.'.7 7 6.p+8.b.f.i.k.k.7 7 7 y.B.B.E.E.C.7 7 J.R.V.V. + +-+-+-+/+/+|+|+7+7 7 7 8+9+9+9+0+n+7 7 b+b+b+c+c+7 7 7 k+e+e+e+e+m+7 7 s+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+C+7 C+e+e+e+e+e+e+d+c+c+c+b+b+ @7 7 n+0+9+9+9+q+7 7 .@7+|+|+/+'+7 7 7 + +V.V.U.7 7 *+I.E.E.B.z.7 7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.%.7 7 M z z x v s R 7 7 3+i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n +@7 7 7 @@z z N T Z +.#.7 7 1.7.8.8.b.f.i.k.k.7 7 7 y.B.B.E.E.*+7 7 7 7 7 7 7 7 '+>+-+/+/+|+|+7+7 7 7 8+9+9+9+0+H+7 7 D+b+b+c+c+k+7 7 7 f+e+i+t+n+7 7 B+o+o+o+o+m+7 7 s+o+o+o+o+o+o+o+o+o+o+o+o+`+j+o+e+e+e+e+e+e+d+c+c+c+b+b+z+7 7 7 L+9+9+9+h+7 7 n+E+|+5+U.}+7 7 7 + +V.V.Q.7 7 7 T+E..+D.G.t.7 7 u.k.k.i.f.c.7 7 4.<.{.;.&.+.O 7 H z z x v t 7 7 #@k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i E j $@R 7 7 7 q.B y M V ` 7 7 O :.<.3.8.8.b.f.v+l.Y+7 7 7 %@z.Y.E.E.K.P.7 7 7 7 7 7 7 7 7 U./+/+6+5+&@7 7 7 &@h+*@9+0+Z+7 7 @z+L+c+c+=@n+7 7 7 7 7 n+C+`+7 n+s+C+s+B+n+7 7 j+s+J+o+o+o+o+o+o+o+o+J+B+7 n+s+i+e+e+e+e+e+d+c+c+c+D+z+ @7 7 7 7 M+*@9+8+n+7 7 7 7 7 '+/+7 7 7 #+W.V.V.R.O.7 7 7 7 7 G.Y.t.7 7 6.l.P+j.++6.7 7 1.(._.;.&.+. .O 7 A C x w R 7 p m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i S l p p u u u u A A P P ` $.W+;.{.<.3.8.8.b.f.G+c.c.t.t.t.t.C.-@E.E.K.P.O.J.S.W.W.W.Z.7 7 7 (+/+4+q+q+q+q+q+q+H+x+9+0+0+y+j+7 7 j+c+c+c+K+m+7 7 n+k+i+o+C+j+7 n+J+m+m+m+m+m+m+m+B+o+o+o+o+o+o+o+o+B+m+m+m+m+A+e+e+e+e+e+d+c+c+c+R+ @ @ @ @H+H+H+x+9+8+;@>@7 7 >@5+/+/+'+'+'+#+#+V.V.R.N.Q.G.7 7 *+Y.B.F+t.t.t.c.,@c.c.c.0.0.}.}.:.;.&.+.Z T '@H 7 7 7 u [.q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.F.7 7 N.N.R.V.V. + +'+7 7 '+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B..+7 7 C.N.N.R.V.V. + +,+7 7 '+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.F.7 7 C.N.N.R.V.V. + +>+7 7 :+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.M.7 7 7 w+N.R.V.V. + +U.7 U./+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.C.7 7 O.w+R.V.V.$+Z.7 Z.)+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.T+G.7 7 O.O.Z.7 Z.>+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+o+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+d+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+m+7 7 7 7 f+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+e+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z y M V V $.=.'.(.2.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.F.J.J.J.J.S.`.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+K+n+7 7 I+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+d+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+_+:+,+;+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z A P 7 7 7 7 ` ` |.3.8.8.b.f.i.c.c.s.v.v.y.B.B.E.C.C.G.7 P.O.X.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+m+7 7 z+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+:+7 7 '+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N P 7 7 ` ;.{.<.3.8.8.b.f.i.7 7 s.v.v.y.B.B.E.E.I.J.P.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+c+c+c+m+7 7 z+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+b+b+b+a+a+0+0+9+9+9+8+8+7+7+7+|+|+:+7 7 '+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N W 7 7 Y ;.{.<.3.8.8.b.f.j.7 7 u.v.v.y.B.B.E.E.I.C.1+N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+c+c+c+c+m+7 7 z+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+c+z+m+7 z+c+c+c+c+c+c+c+c+c+c+c+c+b+b+b+a+a+0+0+*@H+n+q+8+7+7+7+|+|+Q+'+'+>+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N X 7 7 7 ;.{.<.3.8.8.b.f.c.7 7 ]+v.v.y.B.B.E.E.I.7 2+N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+b+b+b+ @7 7 z+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+ @7 7 z+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+a+a+0+0+h+7 7 q+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T O 7 7 '.{.<.3.8.8.b.f.7 7 7 6.v.v.y.B.B.E.E.M.G.N.N.R.V.V. + +-+-+-+/+/+|+|+7+7+7+8+8+9+9+9+0+0+a+a+b+b+b+b+b+b+ @7 7 z+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+ @7 7 z+b+b+b+b+b+b+b+b+b+b+b+b+b+b+b+a+a+0+0+h+7 7 q+8+7+7+7+|+|+/+/+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T =+7 7 ` {.<.3.8.8.b.g.7 6.7 7 )@v.y.B.B.E.E.*+*+N.N.R.V.V. + +-+)+>+'+'+q+5+7+7+7+8+8+*@h+h+y+y+Z+b+b+L+ @L+b+b+ @7 7 z+b+b+b+R+z+z+z+z+R+b+b+b+b+D+L+ @ @ @z+D+b+b+D+z+j+7 7 X+z+z+z+b+b+b+b+D+z+ @ @ @X+R+b+a+a+0+y+r+7 7 N+h+g+g+E+4+5+:+:+,+;+-+ + +V.V.R.N.N.J.C.C.C.F+Y.y.v.v.s.k.l.j.g.9.9.8.3.<.:.` ` #.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T V 7 7 O {.<.3.8.8.b.c.c.Y+7 7 !@v.y.B.B.E.E.G.M.N.N.R.V.V. + +&+7 7 (+:+q+7 n+~@7+8+8+x+H+7 7 7 @D+n+7 7 @a+a+ @7 7 y+a+a+a+L+ @7 7 @L+a+a+a+y+7 7 X+y+X+7 7 Z+a+y+7 7 7 7 7 7 7 7 a+a+D+j+7 7 @ @j+7 7 L+a+a+0+7 7 7 7 7 7 7 7 g+(+q+7 7 7 '+-+ + +V.V.R.J.G.7 C.F.H.7 7 F+v.v.s.k.c.6.7 7 7 8.4.6.7 7 7 7 ` T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z 7 7 7 ^.<.3.8.8.b.7 j.l.7 7 t.v.y.B.B.E.M.7 I.N.N.R.V.V. +#+7 7 ;+/+/+|+q+7 7 g+8+8+9+9+M+7 7 @j+7 7 7 @a+a+ @7 7 y+a+a+a+a+y+7 y+a+a+a+a+Z+7 7 X+a+a+a+X+7 y+a+a+a+ @7 7 y+a+a+a+a+a+y+7 7 y+a+a+a+j+7 7 Z+a+0+0+h+7 7 q+8+7+7+7+|+|+(+7 7 '+-+ + +V.V.S.7 7 *+I.E.E.z.7 7 t.v.s.k.k.v+7 7 7 9.7 }.(.!.7 7 7 U N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z Y 7 7 :.<.3.8.8.9.7 i.k.7 7 7 v.y.B.B.E.*+C.I.N.N.R.V.V.W.7 7 &+-+/+/+|+|+7 7 n+8+8+9+9+h+7 7 7 n+Z+{@7 H+0+0+H+7 7 y+0+0+0+{@n+L+0+0+0+0+0+r+7 7 y+0+0+0+y+7 y+0+0+0+H+7 7 y+0+0+0+0+0+y+7 7 0+0+0+0+L+7 7 L+0+0+0+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +V.`.U.7 G.I.I.E.E.B.C.7 7 ]@s.k.k.i.7 7 7 1.^+<.{.;.` 7 7 O+N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z #.7 7 ` <.3.8.8.c.c.i.k.c.7 7 w.y.B.B.E.G.J.I.N.N.R.V.V.U.7 7 ;+-+/+/+|+|+q+7 7 ^@8+9+9+y+7 7 n+{@0+0+j+H+0+0+H+7 7 y+0+0+0+j+H+0+0+0+0+0+0+H+7 7 y+0+0+0+y+7 y+0+0+0+H+7 7 y+0+0+0+0+0+{@y+y+0+0+0+0+y+7 7 H+0+0+0+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +V.T.7 7 1+I.I.E.E.B.z.7 7 m.s.k.k.i.7 7 7 p+3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z @.7 7 7 <.3.8.8.7 g.i.k.n.7 7 ]+y.B.B..+7 I.I.N.N.R.V.X.7 7 7 -+-+/+/+|+|+g+7 7 n+8+9+9+h+7 7 H+9+9+9+9+9+9+9+H+7 7 h+9+9+H+n+*@9+9+9+9+9+9+H+7 7 N+9+9+9+9+9+9+9+9+9+H+7 7 h+9+9+9+9+9+9+9+9+9+9+9+9+h+7 7 H+9+9+9+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +V.U.7 7 J.I.I.E.E.B.B.7 7 7 ]@k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.7 7 7 (.3.8.9.7 f.i.k.P+7 7 6.y.B.B.H.C.I.I.N.N.R.V.W.7 7 Z.-+-+/+/+|+|+~@7 7 7 8+9+9+h+7 7 H+9+9+9+9+9+9+9+H+7 7 h+9+h+7 x+9+9+9+9+9+9+9+M+7 7 7 H+9+9+9+9+9+9+9+9+H+7 7 h+9+9+9+9+9+9+9+9+9+9+9+9+h+7 7 H+9+9+9+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +V.7 7 7 w+I.I.E.E.B.B.6.7 7 u.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.` 7 7 ~.3.8.0.c.f.i.k.k.6.7 7 /@B.B.~+F.I.I.N.N.R.V.O.7 7 '+-+-+/+/+|+|+7+7 7 7 h+9+9+h+7 7 H+9+9+9+9+9+9+9+H+7 7 h+*@7 M+9+9+9+9+9+9+9+9+9+n+7 7 7 n+h+9+9+9+9+9+9+H+7 7 h+9+9+9+9+9+9+9+9+9+x+h+h+r+7 7 H+9+9+9+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +W.7 7 7 N.I.I.E.E.B.B.t.7 7 t.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.=.7 7 1.3.8.7 9.f.i.k.k.t.7 7 F+B.Y.7 .+I.I.N.N.R.V.O.7 7 '+-+-+/+/+|+|+7+7 7 7 h+8+8+h+7 7 q+8+8+8+8+8+8+8+q+7 7 &@n+7 n+8+8+8+8+8+8+8+8+8+(@N+7 7 7 7 q+(@8+8+8+8+q+7 7 h+8+8+8+8+8+8+(@q+7 7 q+q+N+7 7 q+8+8+8+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +W.7 7 7 N.I.I.E.E.B.B.t.7 7 t.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.-.7 7 7 7.9.7 b.f.i.k.k.u.7 7 t.B.F+~+E.I.I.N.N.R.V.O.7 7 '+-+-+/+/+|+|+7+7 7 7 h+8+8+h+7 7 q+8+8+8+8+8+8+8+q+7 7 &@N+7 7 q+8+8+8+8+8+8+8+8+8+8+^@7 7 7 7 n+(@8+8+8+q+7 7 h+8+8+8+8+8+h+7 7 n+(@8+8+h+7 7 q+8+8+8+h+7 7 q+8+7+7+7+|+|+:+7 7 '+-+ + +W.7 7 7 N.I.I.E.E.B.B.t.7 7 t.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.O 7 7 4.0.0.b.f.i.k.k.s.7 7 7 B.~+H.E.I.I.N.N.R.V.O.7 7 '+-+-+/+/+|+|+7+7 7 7 g+7+7+g+7 7 q+7+7+7+7+7+7+7+q+7 7 g+E+7 7 7 g+7+7+7+7+7+7+7+7+7+7+E+>@7 7 7 n+E+7+7+q+7 7 g+7+7+7+7+E+n+7 7 E+7+7+7+g+7 7 q+7+7+7+g+7 7 q+7+7+7+7+|+|+:+7 7 '+-+ + +W.7 7 7 N.I.I.E.E.B.B.t.7 7 t.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.~.7 7 }.7 9.b.f.i.k.k.s.m.7 7 F+7 .+E.I.I.N.N.R.V.!+7 7 '+-+-+/+/+|+|+E+7 7 7 E+7+7+g+7 7 q+7+7+7+7+7+7+7+q+7 7 g+7+.@7 7 n+E+7+7+7+7+7+7+7+7+7+7+7+.@7 7 7 .@7+7+q+7 7 g+7+7+7+7+.@7 7 >@7+7+7+7+g+7 7 q+7+7+7+g+7 7 q+7+7+7+7+|+|+:+7 7 '+-+ + +`.7 7 7 N.I.I.E.E.B.B.m.7 7 !@k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.'.7 7 7 7 8.b.f.i.k.k.s.!@7 7 G.~+E.E.I.I.N.N.R.V.W.7 7 U.-+-+/+/+|+7+g+7 7 7 7+7+7+g+7 7 q+7+7+7+7+7+7+7+q+7 7 g+7+7+q+7 7 q+7+7+7+7+7+7+7+7+7+7+7+7+&@7 7 q+7+7+q+7 7 g+7+7+7+7+q+7 7 q+7+7+7+7+g+7 7 q+7+7+7+g+7 7 q+7+7+7+7+|+|+:+7 7 '+-+ + +V.7 7 7 2+I.I.E.E.B.B.7 7 7 u.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.7 7 7 0.8.b.f.i.k.k.s.]@7 7 7 D.E.E.I.I.N.N.R.V.V.7 7 7 -+-+/+/+|+|+_@7 7 q+|+|+|+5+7 7 q+|+|+|+|+|+|+|+q+7 7 5+|+|+6+n+7 7 (+|+|+|+|+q+7 |+|+|+|+|+5+7 7 q+|+|+q+7 7 5+|+|+|+|+q+7 7 q+|+|+|+|+5+7 7 q+|+|+|+5+7 7 q+|+|+|+|+|+|+:+7 7 '+-+ + +V.O.7 7 J.I.I.E.E.B.-@7 7 7 s.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;./.7 7 5.8.b.f.i.k.k.s.v.6.7 7 -@E.E.I.I.N.N.R.V.V.&+7 7 ,+-+/+|+|+|+n+7 7 4+|+|+|+5+7 7 q+|+|+|+|+|+|+|+q+7 7 5+|+|+|+5+7 7 7 6+|+|+|+q+7 |+|+|+|+|+5+7 7 (+|+|+_@7 7 5+|+|+|+|+q+7 7 n+|+|+|+|+5+7 7 q+|+|+|+4+7 7 q+|+|+|+|+|+|+:+7 7 '+-+ + +V.X.7 7 O.I.I.E.E.B.D.7 7 ]+s.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.:.7 7 p+8.b.f.i.k.k.s.v.t.7 G.B.E.E.I.I.N.N.R.V.V. +U.7 Z.-+/+/+/+:+7 7 }+/+/+/+/+:+7 7 '+/+/+/+/+/+/+/+'+7 7 :+/+/+/+/+'+7 7 U./+/+/+'+7 Q+/+/+/+/+}+7 7 _+/+/+:+7 7 (+/+/+/+/+Q+7 7 7 '+/+/+:+U.U.7 Z./+/+/+/+7 7 Z./+/+/+/+/+/+:+7 7 '+-+ + +V.V.T.7 7 K.I.E.E.Y.G.7 6.v.s.k.k.i.7 7 7 8.3.<.{.;.=.7 7 P N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;._.7 1.8.8.b.f.i.k.k.s.v.w.7 D.B.E.E.I.I.N.N.R.V.V. +$+U.7 '+_+/+:+U.7 '+/+/+/+_+:+U.7 7 7 (+Q+/+/+/+Q+(+7 7 7 U.:+_+/+/+/+U.7 7 Z.:+/+'+7 U.Q+/+/+(+7 7 :+/+/+/+/+U.7 U.:+:+Q+/+/+'+7 7 7 7 7 7 :+Q+7 7 (+Q+/+/+}+7 7 (+:+:+/+Q+:+Z.7 7 U.>+W. +V.V.R.O.7 G.M.E..+~+7 6.)@v.s.k.l.c.7 7 7 0.4.<.^.'.O 7 7 7 '@D z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.7 5.8.8.b.f.i.k.k.s.v.v.7 z.B.E.E.I.I.N.N.R.V.V. + +-+>+Z.7 7 7 '+;+-+-+-+-+;+'+'+'+'+'+'+>+-+-+-+>+'+'+'+'+'+'+;+-+-+-+;+'+'+'+'+-+-+;+'+U.7 7 7 '+;+-+-+-+-+-+)+'+7 7 U.;+-+-+-+&+U.7 7 '+;+-+-+&+7 7 >+-+-+-+&+U.7 7 >+-+>+'+'+'+'+'+'+#+ +V.V.R.N.2+C.7 7 7 ~+F+y.v.v.s.k.c.c.c.c.0.0.}.<._.` ` ` ` P P B z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.R.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.V.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.R.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.N.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.I.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.E.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.y.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.B.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.y.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.s.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.v.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.s.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.8.8.b.f.i.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.:@<@<@<@[@k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.}@<@<@<@|@k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.|@1@2@3@2@1@k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.k.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.4@<@<@i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.5@6@6@i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.7@<@<@i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.2@<@8@i.6@2@i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.i.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.9@<@9@f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.1@<@0@f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.9@<@9@f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.a@<@9@f.f.9@9@f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.f.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.b@<@c@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.a@9@a@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.d@9@c@b.b.b.b.0@<@c@b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.b.0@<@e@b.b.c@e@b.b.b.b.b.b.b.b.b.b.b.b.[@c@0@b.b.b.b.b.b.b.b.b.b.b.b.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N T Z +.&.;.{.<.3.<@<@4@8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.2@<@4@8.8.8.8.<@<@4@8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.<@<@f@8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.c@<@9@8.8.8.8.8.8.8.8.8.8.8.8.8.8.3.<.{.;.&.+.Z T N z z x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z N g@h@i@&.;.{.<.f@<@<@j@8.j@4@4@8.8.8.8.8.8.8.4@4@4@8.8.8.8.8.8.8.8.8.j@4@j@8.8.8.8.8.8.8.8.8.8.8.8.8.4@4@j@8.8.8.8.8.8.f@4@f@8.8.8.8.8.8.8.8.8.8.8.8.8.<@<@f@8.8.8.f@<@<@j@8.j@4@4@8.8.8.8.8.8.8.j@4@4@8.8.8.8.8.8.8.8.8.8.8.4@<@<@8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.8.9@<@c@8.8.8.8.8.8.8.8.8.8.8.8.8.8.3.<.{.;.&.+.i@g@N z z x v k@k@l@m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z m@n@o@h@p@2@;.{.3.q@<@<@3.r@<@<@<@s@3.3.3.t@s@<@s@s@<@2@t@3.t@2@<@<@r@q@<@<@q@s@<@<@<@3.3.u@2@<@<@q@q@2@<@<@2@t@3.3.3.t@b@2@q@s@2@2@<@<@r@3.3.3.3.3.3.s@<@<@<@<@<@s@3.q@<@<@3.r@<@<@<@s@3.3.3.3.t@b@r@q@2@2@u@3.3.3.3.3.3.3.t@<@<@<@<@<@<@q@u@2@<@<@q@3.3.b@<@<@s@3.q@<@<@<@<@<@<@:@<@<@<@3.3.u@2@<@<@q@3.q@<@<@<@v@p@<@<@N z z w@x@k@y@<@z@k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x A@<@B@T Z h@<@;.<.<.s@<@s@s@r@C@s@<@<@<.<.<.r@<@C@<.<.s@<@s@<.<.<.<@<@s@2@b@<@D@<.C@<@b@<.<.<.C@<@<@C@b@C@:@<@<@C@<.<.D@2@<@D@<.D@<@2@<.D@<.<.<.<.<.<.<.<.r@<@2@<.<.<.<.s@<@s@s@r@C@s@<@<@<.<.<.D@2@:@<.<.C@<@b@<.<.<.<.<.<.<.<.<.s@<@s@<.<.<.<.C@<@<@D@<.<.<.<@<@:@<.<.E@<@<@E@<.<.<.s@<@b@<.<.<.C@<@<@D@<.<.C@<@<@p@B@n@B@N z F@x@v s s <@<@G@i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x H@<@g@T Z h@p@{.{.{.b@<@2@I@{.{.J@<@<@{.{.{.K@L@{.{.{.s@<@s@{.{.M@<@<@s@{.J@<@{.{.s@<@s@{.{.{.K@<@<@J@{.{.{.<@<@J@{.{.b@<@L@{.{.{.<@<@M@{.{.{.{.{.{.{.{.{.s@<@s@{.{.{.{.b@<@2@I@{.{.J@<@<@{.{.{.2@2@{.{.{.J@<@<@{.{.{.{.{.{.{.{.{.<@<@K@{.{.{.{.J@<@<@{.{.{.M@<@<@J@{.{.J@<@<@{.{.{.{.s@<@s@{.{.{.L@<@<@{.{.{.L@<@<@N@+.o@o@N w@<@O@v s s <@<@P@i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x <@<@Q@T Z i@R@;.;.;.<@<@N@;.;.;.s@<@s@;.;.;.;.;.;.;.;.<@<@K@;.;.N@<@<@;.;.S@R@;.;.b@<@N@;.;.;.s@<@s@;.;.;.N@<@<@;.;.S@<@<@N@;.;.;.<@<@N@;.;.;.;.;.;.;.;.;.<@<@N@;.;.;.;.<@<@N@;.;.;.s@<@s@;.;.L@<@s@;.;.;.N@<@<@;.;.;.;.;.;.;.;.S@<@<@N@;.;.;.;.s@<@s@;.;.;.N@<@<@;.;.;.s@<@s@;.;.;.;.<@<@N@;.;.;.s@<@s@;.;.;.s@<@s@&.+.i@T@U@<@<@x v s s <@<@P@i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x n@<@n@g@Z &.&.&.&.v@<@<@V@&.&.&.B@<@L@&.&.&.&.&.&.&.V@<@<@N@&.&.p@<@p@&.&.&.&.&.&.<@<@v@&.&.&.2@<@K@&.&.&.K@<@2@&.&.N@<@<@&.&.&.v@<@<@v@&.&.&.&.&.&.&.&.V@<@<@v@&.&.&.v@<@<@V@&.&.&.B@<@L@&.&.<@<@N@&.&.&.p@<@2@&.&.&.&.&.&.&.&.N@<@<@&.&.&.&.&.B@<@L@&.&.&.L@<@2@&.&.&.B@<@L@&.&.&.V@<@<@v@&.&.&.2@<@L@&.&.&.<@<@N@&.+.Z T F@<@F@x v s k@<@<@W@i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x X@<@<@<@Y@+.+.+.+.h@<@<@+.+.+.+.<@<@h@+.+.+.Z@Y@p@p@B@<@<@+.+.+.B@<@`@+.+.+.+.+.i@<@<@+.+.+.+.<@<@h@+.+.+.p@<@p@+.+.h@<@<@+.+.+.Y@<@B@+.+.+.+.+.+.+.+.+.h@<@<@+.+.+.+.h@<@<@+.+.+.+.<@<@h@+.h@<@<@p@p@p@p@p@p@Y@+.+.+.+.+.+.+.+.`@<@B@+.+.+.+.+.<@<@h@+.+.+.p@<@p@+.+.+.<@<@h@+.+.+.h@<@<@+.+.+.+.<@<@h@+.+.Z@<@<@i@+.+.Z T <@<@H@F@y@y@y@ #.#k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z X@<@<@<@o@Z Z Z o@<@o@Z Z Z i@<@<@Z Z Z +#<@n@i@Z @#<@n@Z Z Z <@<@h@Z Z Z Z Z +#<@B@Z Z Z h@<@<@Z Z Z Z n@<@h@Z Z ##<@<@Z Z Z n@<@##Z Z Z Z Z Z Z Z Z @#<@B@Z Z Z Z o@<@o@Z Z Z i@<@<@Z Z @#<@<@Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z o@<@o@Z Z Z Z i@<@<@##Z Z Z <@<@+#Z Z i@<@<@##Z Z Z @#<@B@Z Z Z h@<@<@##Z Z h@<@<@Z Z Z Z i@<@<@m@x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z z g@n@<@<@i@T T B@<@@#T T T g@<@n@T T +#<@n@T@T T B@<@o@T T i@<@<@T@T T T T T o@<@o@T T T +#<@n@T T T T <@<@i@T T T g@<@g@T o@n@g@T T T T T T T T T T B@<@o@T T T T B@<@@#T T T g@<@n@T T o@<@<@T T T T T T T T T T T T T T T <@<@g@T T T T +#<@<@T T T T <@<@g@T T +#<@<@T T T T B@<@o@T T T g@<@<@T T T @#<@B@T T T T g@<@<@m@x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s v x z N N g@<@<@g@N N <@<@g@N N N F@<@F@N N <@<@@#N N N <@<@Q@N N g@<@n@N N N N N N n@<@g@N N N F@<@F@N N N g@<@<@N N N N U@B@@#F@Q@$#N N N N N N N N N N N <@<@g@N N N N <@<@g@N N N F@<@F@N N F@<@<@N N N N N N N N N N N N N N $#<@<@U@N N N N F@<@F@N N N g@<@<@N N N F@<@F@N N N N <@<@g@N N N F@<@F@N N N F@<@@#N N N N g@<@<@m@x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s %#<@z z z z <@<@A@z A@<@<@&#z z z H@<@m@z m@<@<@m@z z A@<@<@m@z z F@<@F@z z z z z &#<@<@m@z z z n@<@X@z z z X@<@F@z z z m@<@&#z z z z z z z z z z z z z z A@<@<@m@z z z A@<@<@&#z z z H@<@m@z z F@<@<@z z z z z z z z z z z z z z m@<@<@z z z z z n@<@X@z z z X@<@n@z z z n@<@F@z z z A@<@<@&#z z z H@<@w@z z z <@<@m@z z z z m@<@<@m@x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s *#F@z z z &#<@n@z z m@<@n@z z z z <@<@A@z m@<@<@m@z z X@<@<@z z z H@<@X@z z z z z m@<@<@z z z z <@<@A@z z z F@<@w@z z z <@<@w@m@m@m@A@z z z z z z z z z z m@<@<@z z z z m@<@n@z z z z <@<@A@z z A@<@<@X@z z z z z z z z z z z z z w@<@H@z z z z z <@<@m@z z X@n@<@F@z z z <@<@m@z z z m@<@<@z z &#w@<@<@m@z z &#<@<@&#z z z z z n@<@H@x v s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s F@x@x x x F@<@O@x x x@<@x@=#x x -#<@<@O@x O@<@<@n@;#w@F@n@<@x x O@<@<@-#x x x x =#F@<@<@O@x x -#<@<@O@x x =#<@<@w@x x x x@<@<@<@<@<@<@n@=#x x x x x x x x ;#<@<@=#=#x x x@<@x@=#x x -#<@<@O@x x x F@<@<@w@;#;#F@w@x x x x x x x =#x@<@x@=#x x x x <@<@n@F@n@;#n@<@x@x x x <@<@-#x =#x ;#<@<@x@F@n@;#<@<@-#x x w@<@<@=#x x x x x ;#<@<@x@%#k@>#x@m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s v ,#>#x@y@x@y@,#v ,#y@y@y@y@y@v >#y@y@y@y@'#v >#<@<@x@%#v *#<@x@*#y@y@y@y@*#v v '#y@y@y@y@y@'#>#y@y@y@y@'#%#y@y@y@y@*#v ,#x@*#%#%#%#>#<@<@y@v v v v v v v v v >#<@<@x@,#y@y@y@y@y@v >#y@y@y@y@'#v v v >#n@<@<@x@*#,#v v v v v v '#y@y@y@y@y@'#v v v %#<@<@x@'#v y@y@y@*#v v %#n@<@n@'#v v y@<@<@>#,#'#y@y@y@'#y@y@y@y@y@'#v v v v v %#x@<@<@n@>#)#m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n q s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s k@<@>#s s s s s y@<@y@s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k n s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s n@<@k@s s s s s x@<@!#s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i k q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q <@<@~#q q q q {#<@ #q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q q m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m z@<@n@]#m ^#z@<@z@m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k k i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e g i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c e i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i i g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b c g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g g e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 b e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 0 c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c c b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 8 b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b b 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 2 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 1 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } | 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < [ } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : < } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ : [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( _ < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / ( : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : : _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ / _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] ^ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ] / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ { ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! ~ ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] ] { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ! { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { { ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ) ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ' ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > , ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; > ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > ; ; - = * & % $ # @ + ", +". + @ # $ % & * = - ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; - = * & % $ # @ + ", +". + @ # $ % & * = ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; - = * & % $ # @ + ", +". + @ # $ % & * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - = * & % $ # @ + ", +". + @ # $ % & = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = * & % $ # @ + ", +". + @ # $ % * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * & % $ # @ + ", +". + @ # $ & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & % $ # @ + ", +". + @ # % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % $ # @ + ", +". + @ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ # @ + ", +". + # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # @ + ", +". @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + ", +"+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "}; diff --git a/gtk2_ardour/about.cc b/gtk2_ardour/about.cc new file mode 100644 index 0000000000..f5f127cea3 --- /dev/null +++ b/gtk2_ardour/about.cc @@ -0,0 +1,498 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "utils.h" +#include "version.h" + +#include +#include + +#include "about.h" +#include "rgb_macros.h" +#include "ardour_ui.h" + +#include "i18n.h" + +using namespace Gtk; +using namespace std; +using namespace SigC; +using namespace ARDOUR; + +#ifdef WITH_PAYMENT_OPTIONS + +/* XPM */ +static const gchar * paypal_xpm[] = { +"62 31 33 1", +" c None", +". c #325781", +"+ c #154170", +"@ c #C1CDDA", +"# c #4E6E92", +"$ c #D1D5DA", +"% c #88A0B8", +"& c #B4C4D3", +"* c #C8D3DE", +"= c #D7E1E9", +"- c #002158", +"; c #F6F8FA", +"> c #44658B", +", c #E7ECF0", +"' c #A4B7CA", +") c #9DB0C4", +"! c #E3F1F7", +"~ c #708CA9", +"{ c #E1E7ED", +"] c #567698", +"^ c #7C96B1", +"/ c #E7F5FA", +"( c #EEF1F4", +"_ c #6883A2", +": c #244873", +"< c #BBBBBB", +"[ c #E9E9E9", +"} c #063466", +"| c #22364D", +"1 c #94A7BD", +"2 c #000000", +"3 c #EAF7FC", +"4 c #FFFFFF", +"1'111111111111111111111111111111111111111111111111111111111%_#", +"%333333333333333333333333333333333333333333333333333333333333.", +"%444444444444444444444444444444444444444444444444444444444444:", +"_4333333!!!!!!33333333333333333333!!!!!!33333333333!%%%%1334[:", +"_444444@+}}}}+>)44444444444444444,:}}}}}.^(44444444@}..+.44($:", +"_433333^:&&&&)_}_33///33333333333&+)&&&'~+./3///333^.(;#]33($:", +"_444444>_444444'}_>...#%####~,]##..444444=+#]...>1;#_4;.144($:", +"_43333!+'4,>#=4(:+_%%%]}}#~#}_+~~:]44_>&44#}_%%%_+>:14=}@33($:", +"_44444*+$4&--)4(+%44444%-)4=--'4{+14,}-~44##44444&}}*4)+444($:", +"_433331:;4):_;4*}_]:.$4*-~4{}>44#-=4@.#{4;+>_:.&4,++;4_#333($:", +"_44444_#444444=.-.%&*,41-#4(:@4'-:(44444(_-:^&*,4*}#44.%444($:", +"_43333:%4;@@'~+-%44*&44]-.;;'4,:-#44*@&%:-];4{'(4)-%4{+&333($:", +"_4444{}@4*}}+>#:;4^-#4;.>+,444_+:^4(:}+.]}=4'-+(4_-&4&+{444($:", +"_4333'+(41:*=3'.44*)(4=+)+*44@}%+@4=}&=/@}{4{1{44:+,4^.3333($:", +"_4444~>,,]#444*})(;**,':*}'4;._@}=,%:444(+~(;{&,*}.,,>~4444($:", +"_4333>}}}}^3333~}::}}}}>].;4^+=~}}}}]3333'}+:}}}}}}}}}'3333($:", +"_4444$@@@@(44444$))@*@*^}$4=}14=@@@@{44444=))&*@@@@@@@;4444($:", +"_433333333333333333333=+:%%.>/33333333333333333333333333333($:", +"_4444444444444444444441....>=444444444444444444444444444444($:", +"_4333333333333333333333333333333333333333333333333333333333($:", +"_4444444444444444444444444444444444444444444444444444444444($:", +"_4333333333333333333333333333333333333333333333333333333333($:", +"_4444442222444222442444242444244222242444242222244222244444($:", +"_4333332333232333233232332232233233332233233323332333333333($:", +"_4444442222442222244424442424244222442424244424444222444444($:", +"_4333332333332333233323332333233233332332233323333333233333($:", +"_4444442444442444244424442444244222242444244424442222444444($:", +"_433333333333333333333333333333333333333333333333333333333344:", +"#4([[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[=&:", +".=&<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<1|", +"::||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"}; +#endif + +static gint +stoppit (GdkEventButton* ev, Gtk::Notebook* notebook) +{ + gtk_signal_emit_stop_by_name (GTK_OBJECT(notebook->gtkobj()), + "button_release_event"); + return TRUE; +} + +static const char* author_names[] = { + N_("Marcus Andersson"), + N_("Jeremy Hall"), + N_("Steve Harris"), + N_("Tim Mayberry"), + N_("Mark Stewart"), + N_("Sam Chessman"), + N_("Jack O'Quin"), + N_("Matt Krai"), + N_("Ben Bell"), + N_("Gerard van Dongen"), + N_("Thomas Charbonnel"), + N_("Nick Mainsbridge"), + N_("Colin Law"), + N_("Sampo Savolainen"), + N_("Joshua Leach"), + N_("Rob Holland"), + N_("Per Sigmond"), + N_("Doug Mclain"), + 0 +}; + +static const char* translators[] = { + N_("French:\n\tAlain Fréhel "), + N_("German:\n\tKarsten Petersen "), + N_("Italian:\n\tFilippo Pappalardo "), + N_("Portuguese:\n\tRui Nuno Capela "), + N_("Brazilian Portuguese:\n\tAlexander da Franca Fernandes \ +\n\tChris Ross "), + N_("Spanish:\n\t Alex Krohn "), + N_("Russian:\n\t Igor Blinov "), + 0 +}; + + +About::About (ARDOUR_UI * ui) + : Window (GTK_WINDOW_TOPLEVEL), _ui (ui) +#ifdef WITH_PAYMENT_OPTIONS + , paypal_pixmap (paypal_xpm) +#endif +{ + using namespace Notebook_Helpers; + + about_index = 0; + about_cnt = 0; + drawn = false; + + Gtk::Label* small_label = manage (new Label (_( +"Copyright (C) 1999-2005 Paul Davis\n" +"Ardour comes with ABSOLUTELY NO WARRANTY\n" +"This is free software, and you are welcome to redistribute it\n" +"under certain conditions; see the file COPYING for details.\n"))); + + Gtk::Label* version_label = + manage (new Label + (compose(_("Ardour: %1\n(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)"), + VERSIONSTRING, + gtk_ardour_major_version, + gtk_ardour_minor_version, + gtk_ardour_micro_version, + libardour_major_version, + libardour_minor_version, + libardour_micro_version))); + + Notebook* notebook = manage (new Notebook); + + ScrolledWindow* author_scroller = manage (new ScrolledWindow); + Text* author_text = manage (new Text); + + author_text->set_editable (false); + author_text->set_name (X_("AboutText")); + + string str = _( +"Primary author:\n\t\ +Paul Davis\n\n\ +Major developers:\n\t\ +Jesse Chappell\n\t\ +Taybin Rutkin\n\ +Contributors:\n\t"); + + for (int32_t n = 0; author_names[n] != 0; ++n) { + str += _(author_names[n]); + str += "\n\t"; + } + + author_text->insert (str); + + author_scroller->add (*author_text); + author_scroller->set_usize (-1, 75); + author_scroller->set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + ScrolledWindow* translator_scroller = manage (new ScrolledWindow); + Text* translator_text = manage (new Text); + + translator_text->set_editable (false); + translator_text->set_name (X_("AboutText")); + + str = ""; + + for (int32_t n = 0; translators[n] != 0; ++n) { + str += _(translators[n]); + str += '\n'; + } + + translator_text->insert (str); + + translator_scroller->add (*translator_text); + translator_scroller->set_usize (-1, 75); + translator_scroller->set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + Label* author_tab_label = manage (new Label (_("Authors"))); + Label* translator_tab_label = manage (new Label (_("Translators"))); + + notebook->pages().push_back (TabElem (*author_scroller, *author_tab_label)); + notebook->pages().push_back (TabElem (*translator_scroller, *translator_tab_label)); + + notebook->set_name ("AboutNoteBook"); + notebook->button_release_event.connect_after (bind (slot (stoppit), notebook)); + + logo_pixmap = 0; + logo_height = 0; + logo_width = 0; + + set_name ("AboutWindow"); + set_title ("ardour: about"); + set_wmclass ("ardour_about", "Ardour"); + + vbox.set_border_width (5); + vbox.set_spacing (5); + + if (load_logo_size ()) { + logo_area.set_usize (logo_width, logo_height); + load_logo (*this); + + vbox.pack_start (logo_area, false, false); + logo_area.expose_event.connect (slot (*this, &About::logo_area_expose)); + } else { + expose_event.connect (slot (*this, &About::logo_area_expose)); + } + + small_label->set_name ("AboutWindowSmallLabel"); + version_label->set_name("AboutWindowSmallLabel"); + + first_label.set_name ("AboutWindowLabel"); + third_label.set_name ("AboutWindowPDLabel"); + second_label.set_name ("AboutWindowLabel"); + + subvbox.pack_start (*small_label, false, false); + subvbox.pack_start (*version_label, false, false); + subvbox.pack_start (*notebook, true, true); + +#ifdef WITH_PAYMENT_OPTIONS + paypal_button.add (paypal_pixmap); + + HBox *payment_box = manage (new HBox); + payment_box->pack_start (paypal_button, true, false); + + subvbox.pack_start (*payment_box, false, false); +#endif + + delete_event.connect (bind (slot (just_hide_it), static_cast (this))); + + add (vbox); + add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + + set_position (GTK_WIN_POS_CENTER); + + show_all (); + subvbox.hide (); + + /* wait for the first logo expose event to complete so that + we know we are fully drawn. + */ + + while (!drawn) { + gtk_main_iteration (); + } +} + +About::~About () +{ +} + +void +About::show_sub (bool yn) +{ + if (yn) { + vbox.pack_start (subvbox, true, true); + subvbox.show_all (); + } else { + vbox.remove (subvbox); + subvbox.hide (); + } +} + +gint +About::button_release_event_impl (GdkEventButton* ev) +{ + hide(); + + if (!_ui->shown ()) { + /* show it immediately */ + _ui->show(); + } + + return TRUE; +} + +void +About::realize_impl () +{ + Window::realize_impl (); + get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + // get_window().set_decorations (GdkWMDecoration (0)); +} + +bool +About::load_logo_size () +{ + gchar buf[1024]; + FILE *fp; + string path = find_data_file ("splash.ppm"); + + if (path.length() == 0) { + return false; + } + + if ((fp = fopen (path.c_str(), "rb")) == 0) { + error << compose (_("cannot open splash image file \"%1\""), path) << endmsg; + return false; + } + + fgets (buf, sizeof (buf), fp); + if (strcmp (buf, "P6\n") != 0) { + fclose (fp); + return false; + } + + fgets (buf, sizeof (buf), fp); + fgets (buf, sizeof (buf), fp); + sscanf (buf, "%d %d", &logo_width, &logo_height); + fclose (fp); + return true; +} + +bool +About::load_logo (Gtk::Window& window) +{ + GdkGC* gc; + gchar buf[1024]; + guchar *pixelrow; + FILE *fp; + gint count; + gint i; + string path; + + path = find_data_file ("splash.ppm"); + + if (path.length() == 0) { + return false; + } + + if ((fp = fopen (path.c_str(), "rb")) == 0) { + return false; + } + + fgets (buf, sizeof (buf), fp); + if (strcmp (buf, "P6\n") != 0) { + fclose (fp); + return false; + } + + fgets (buf, sizeof (buf), fp); + fgets (buf, sizeof (buf), fp); + sscanf (buf, "%d %d", &logo_width, &logo_height); + + fgets (buf, sizeof (buf), fp); + if (strcmp (buf, "255\n") != 0) { + fclose (fp); + return false; + } + + Gtk::Preview preview (GTK_PREVIEW_COLOR); + + preview.size (logo_width, logo_height); + pixelrow = new guchar[logo_width * 3]; + + for (i = 0; i < logo_height; i++) { + count = fread (pixelrow, sizeof (unsigned char), logo_width * 3, fp); + if (count != (logo_width * 3)) + { + delete [] pixelrow; + fclose (fp); + return false; + } + preview.draw_row (pixelrow, 0, i, logo_width); + } + + window.realize (); + + logo_pixmap = gdk_pixmap_new (GTK_WIDGET(window.gtkobj())->window, logo_width, logo_height, + gtk_preview_get_visual()->depth); + gc = gdk_gc_new (logo_pixmap); + gtk_preview_put (preview.gtkobj(), logo_pixmap, gc, 0, 0, 0, 0, logo_width, logo_height); + gdk_gc_destroy (gc); + + delete [] pixelrow; + fclose (fp); + + return true; +} + +gint +About::logo_area_expose (GdkEventExpose* ev) +{ + if (!drawn) { + drawn = true; + } + + if (logo_pixmap) { + logo_area.get_window().draw_pixmap (logo_area.get_style()->get_black_gc(), + Gdk_Pixmap (logo_pixmap), + 0, 0, + ((logo_area.width() - logo_width) / 2), + ((logo_area.height() - logo_height) / 2), + logo_width, logo_height); + gdk_flush (); + } + + return FALSE; +} + +#ifdef WITH_PAYMENT_OPTIONS +void +About::goto_paypal () +{ + char buf[PATH_MAX+16]; + char *argv[4]; + char *docfile = "foo"; + int grandchild; + + if (fork() == 0) { + + /* child */ + + if ((grandchild = fork()) == 0) { + + /* grandchild */ + + argv[0] = "mozilla"; + argv[1] = "-remote"; + snprintf (buf, sizeof(buf), "openurl(%s)", docfile); + argv[2] = buf; + argv[3] = 0; + + execvp ("mozilla", argv); + error << "could not start mozilla" << endmsg; + + } else { + int status; + waitpid (grandchild, &status, 0); + } + + } +} +#endif diff --git a/gtk2_ardour/about.h b/gtk2_ardour/about.h new file mode 100644 index 0000000000..363bc57f33 --- /dev/null +++ b/gtk2_ardour/about.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_about_h__ +#define __ardour_gtk_about_h__ + +#include +#include +#include + +class ARDOUR_UI; + +class About : public Gtk::Window +{ + public: + About (ARDOUR_UI *); + ~About (); + + void show_sub (bool yn); + + protected: + void realize_impl (); + + private: + Gtk::DrawingArea logo_area; + GdkPixmap* logo_pixmap; + Gtk::Label first_label; + Gtk::Label second_label; + Gtk::Label third_label; + Gtk::VBox vbox; + Gtk::VBox subvbox; + + vector authors; + vector supporters; + + uint32_t about_index; + uint32_t about_cnt; + int logo_height; + int logo_width; + bool drawn; + bool support; + ARDOUR_UI * _ui; + + SigC::Connection timeout_connection; + + bool load_logo_size (); + bool load_logo (Gtk::Window&); + gint logo_area_expose (GdkEventExpose*); + + gint button_release_event_impl (GdkEventButton*); + gint start_animating (); + void stop_animating (); + + void gone_hidden (); + +#ifdef WITH_PAYMENT_OPTIONS + Gtk::Pixmap paypal_pixmap; + Gtk::Button paypal_button; + void goto_paypal (); +#endif +}; + +#endif /* __ardour_gtk_about_h__ */ diff --git a/gtk2_ardour/add_route_dialog.cc b/gtk2_ardour/add_route_dialog.cc new file mode 100644 index 0000000000..669248a371 --- /dev/null +++ b/gtk2_ardour/add_route_dialog.cc @@ -0,0 +1,148 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include + +#include + +#include "utils.h" +#include "add_route_dialog.h" +#include "i18n.h" + +using namespace Gtk; +using namespace Gtkmmext; +using namespace SigC; + +extern std::vector channel_combo_strings; + +AddRouteDialog::AddRouteDialog () + : ArdourDialog ("add route dialog"), + ok_button (_("OK")), + cancel_button (_("Cancel")), + track_button (_("Tracks")), + bus_button (_("Busses")), + routes_adjustment (1, 1, 32, 1, 4), + routes_spinner (routes_adjustment) +{ + set_name ("AddRouteDialog"); + set_title (_("ardour: add track/bus")); + set_wmclass (X_("ardour_add_track_bus"), "Ardour"); + set_position (GTK_WIN_POS_MOUSE); + set_keyboard_input (true); + + name_template_entry.set_name ("AddRouteDialogNameTemplateEntry"); + track_button.set_name ("AddRouteDialogRadioButton"); + bus_button.set_name ("AddRouteDialogRadioButton"); + ok_button.set_name ("AddRouteDialogButton"); + cancel_button.set_name ("AddRouteDialogButton"); + routes_spinner.set_name ("AddRouteDialogSpinner"); + + bus_button.set_group (track_button.group()); + track_button.set_active (true); + + HBox *hbrb = manage (new HBox); + + hbrb->set_spacing (6); + hbrb->pack_start (*(manage (new Label (_("Add")))), false, false); + hbrb->pack_start (routes_spinner, false, false); + hbrb->pack_start (track_button, false, false); + hbrb->pack_start (bus_button, false, false); + + channel_combo.set_popdown_strings (channel_combo_strings); + channel_combo.set_value_in_list (true, false); + channel_combo.set_name (X_("ChannelCountSelector")); + channel_combo.get_entry()->set_name (X_("ChannelCountSelector")); + channel_combo.get_popwin()->set_name (X_("ChannelCountSelector")); + + VBox *vbcc = manage (new VBox); + + vbcc->set_spacing (6); + vbcc->pack_start (*(manage (new Label ("Channel configuration"))), false, false); + vbcc->pack_start (channel_combo, false, false); + +#if NOT_USEFUL_YET + HBox *hbnt = manage (new HBox); + + hbnt->pack_start (*(manage (new Label (_("Name (template)")))), false, false); + hbnt->pack_start (name_template_entry, true, true); +#endif + + HBox* hbbut = manage (new HBox); + + set_usize_to_display_given_text (ok_button, _("Cancel"), 20, 15); // this is cancel on purpose + set_usize_to_display_given_text (cancel_button, _("Cancel"), 20, 15); + + hbbut->set_homogeneous (true); + hbbut->set_spacing (6); + hbbut->pack_end (cancel_button, false, false); + hbbut->pack_end (ok_button, false, false); + + HBox* hbbutouter = manage (new HBox); + hbbutouter->set_border_width (12); + hbbutouter->pack_end (*hbbut, false, false); + + VBox* vb2 = manage (new VBox); + + vb2->set_border_width (12); + vb2->set_spacing (6); + vb2->pack_start (*hbrb, false, false); + vb2->pack_start (*vbcc, false, false); +#if NOT_USEFUL_YET + vb2->pack_start (*hbnt, false, false); +#endif + vb2->pack_start (*hbbutouter, false, false); + + add (*vb2); + + delete_event.connect (slot (*this, &ArdourDialog::wm_close_event)); + ok_button.clicked.connect (bind (slot (*this, &ArdourDialog::stop), 0)); + cancel_button.clicked.connect (bind (slot (*this, &ArdourDialog::stop), 1)); +} + +AddRouteDialog::~AddRouteDialog () +{ +} + +bool +AddRouteDialog::track () +{ + return track_button.get_active (); +} + +string +AddRouteDialog::name_template () +{ + return name_template_entry.get_text (); +} + +int +AddRouteDialog::count () +{ + return (int) floor (routes_adjustment.get_value ()); +} + +int +AddRouteDialog::channels () +{ + return channel_combo_get_channel_count (channel_combo); +} diff --git a/gtk2_ardour/add_route_dialog.h b/gtk2_ardour/add_route_dialog.h new file mode 100644 index 0000000000..bbfe1efda6 --- /dev/null +++ b/gtk2_ardour/add_route_dialog.h @@ -0,0 +1,39 @@ +#ifndef __gtk_ardour_add_route_dialog_h__ +#define __gtk_ardour_add_route_dialog_h__ + +#include + +#include +#include +#include +#include +#include + +#include + +#include "ardour_dialog.h" + +class AddRouteDialog : public ArdourDialog +{ + public: + AddRouteDialog (); + ~AddRouteDialog (); + + bool track (); + std::string name_template (); + int channels (); + int count (); + + Gtk::Button ok_button; + Gtk::Button cancel_button; + + private: + Gtk::Entry name_template_entry; + Gtk::RadioButton track_button; + Gtk::RadioButton bus_button; + Gtk::Adjustment routes_adjustment; + Gtk::SpinButton routes_spinner; + Gtk::Combo channel_combo; +}; + +#endif /* __gtk_ardour_add_route_dialog_h__ */ diff --git a/gtk2_ardour/ardbg b/gtk2_ardour/ardbg new file mode 100755 index 0000000000..fd54fe809a --- /dev/null +++ b/gtk2_ardour/ardbg @@ -0,0 +1,12 @@ +#!/bin/sh + +if [ -x ./ardour.bin ] ; then + # scons executable + export LD_LIBRARY_PATH=../libs/ardour + exec gdb ./ardour.bin +else + # autofoo/make executable + export LD_LIBRARY_PATH=../libs/ardour/.libs + exec gdb ./ardour +fi + diff --git a/gtk2_ardour/ardev b/gtk2_ardour/ardev new file mode 100755 index 0000000000..6594e4c11f --- /dev/null +++ b/gtk2_ardour/ardev @@ -0,0 +1,13 @@ +#!/bin/sh + + +if [ -x ./ardour.bin ] ; then + # scons executable + export LD_LIBRARY_PATH=../libs/ardour + exec ./ardour.bin --novst $* +else + # autofoo/make executable + export LD_LIBRARY_PATH=../libs/ardour + exec ./ardour --novst $* +fi + diff --git a/gtk2_ardour/ardour_dialog.cc b/gtk2_ardour/ardour_dialog.cc new file mode 100644 index 0000000000..9a5a64a2f2 --- /dev/null +++ b/gtk2_ardour/ardour_dialog.cc @@ -0,0 +1,169 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include + +#include + +#include "ardour_dialog.h" +#include "keyboard.h" +#include "ardour_ui.h" + + +ArdourDialog::ArdourDialog (string name) + : Gtk::Window (GTK_WINDOW_TOPLEVEL), + KeyboardTarget (*this, name) +{ + session = 0; + kbd_input = false; + running = false; + _run_status = 0; + _within_hiding = false; + hide_on_stop = true; +} + +ArdourDialog::~ArdourDialog () +{ +} + +gint +ArdourDialog::enter_notify_event_impl (GdkEventCrossing *ev) +{ + if (ev->detail != GDK_NOTIFY_INFERIOR) { + Keyboard::the_keyboard().set_current_dialog (this); + } + return FALSE; +} + +gint +ArdourDialog::leave_notify_event_impl (GdkEventCrossing *ev) +{ + if (ev->detail != GDK_NOTIFY_INFERIOR) { + Keyboard::the_keyboard().set_current_dialog (0); + } + return FALSE; +} + +gint +ArdourDialog::unmap_event_impl (GdkEventAny *ev) +{ + _within_hiding = true; + Hiding (); /* EMIT_SIGNAL */ + _within_hiding = false; + return Gtk::Window::unmap_event_impl (ev); +} + +void +ArdourDialog::wm_close() +{ + stop (-1); + ARDOUR_UI::instance()->allow_focus(false); +} + +void +ArdourDialog::wm_doi () +{ + if (!hide_on_stop) { + Hiding (); /* EMIT_SIGNAL */ + } + stop (-1); + delete_when_idle (this); +} + +gint +ArdourDialog::wm_close_event (GdkEventAny* ev) +{ + wm_close (); + return TRUE; +} + +gint +ArdourDialog::wm_doi_event (GdkEventAny* ev) +{ + wm_doi (); + return TRUE; +} + +gint +ArdourDialog::wm_doi_event_stop (GdkEventAny* ev) +{ + stop (-1); + return TRUE; +} + +void +ArdourDialog::set_hide_on_stop (bool yn) +{ + hide_on_stop = yn; +} + +void +ArdourDialog::close () +{ + hide_all (); + + if (kbd_input) { + ARDOUR_UI::instance()->allow_focus (false); + } +} + +void +ArdourDialog::stop (int rr) +{ + _run_status = rr; + + if (hide_on_stop) { + Hiding (); /* EMIT_SIGNAL */ + hide_all (); + + if (kbd_input) { + ARDOUR_UI::instance()->allow_focus (false); + } + } + + if (running) { + Gtk::Main::quit (); + running = false; + } +} + +void +ArdourDialog::run () +{ + show_all (); + + if (kbd_input) { + ARDOUR_UI::instance()->allow_focus (true); + } + + running = true; + Gtk::Main::run (); +} + +void +ArdourDialog::set_keyboard_input (bool yn) +{ + kbd_input = yn; +} + +int +ArdourDialog::run_status () +{ + return _run_status; +} diff --git a/gtk2_ardour/ardour_dialog.h b/gtk2_ardour/ardour_dialog.h new file mode 100644 index 0000000000..d6b1ece72b --- /dev/null +++ b/gtk2_ardour/ardour_dialog.h @@ -0,0 +1,81 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_dialog_h__ +#define __ardour_dialog_h__ + +#include +#include + +#include "keyboard_target.h" + +namespace ARDOUR { + class Session; +}; + +/* + * This virtual parent class is so that each dialog box uses the + * same mechanism to declare its closing, and to have a common + * method of connecting and disconnecting from a Session. + */ +class ArdourDialog : public Gtk::Window, public KeyboardTarget +{ + public: + ArdourDialog (string name); + ~ArdourDialog(); + + bool within_hiding() const { return _within_hiding; } + + void run (); + void stop (int); + void close (); + void set_keyboard_input (bool yn); + void set_hide_on_stop (bool yn); + int run_status(); + + gint enter_notify_event_impl (GdkEventCrossing*); + gint leave_notify_event_impl (GdkEventCrossing*); + gint unmap_event_impl (GdkEventAny *); + + ARDOUR::Session *session; + + virtual void set_session (ARDOUR::Session* s) { + session = s; + } + + virtual void session_gone () { + set_session (0); + } + + void quit (); + void wm_close(); + void wm_doi (); + gint wm_close_event (GdkEventAny *); + gint wm_doi_event (GdkEventAny *); + gint wm_doi_event_stop (GdkEventAny *); + + private: + int _run_status; + bool _within_hiding; + bool kbd_input; + bool running; + bool hide_on_stop; +}; + +#endif // __ardour_dialog_h__ diff --git a/gtk2_ardour/ardour_image_compositor_socket.h b/gtk2_ardour/ardour_image_compositor_socket.h new file mode 100644 index 0000000000..ad0a7b79c6 --- /dev/null +++ b/gtk2_ardour/ardour_image_compositor_socket.h @@ -0,0 +1,167 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + + +#ifndef __ardour_image_comp_h__ +#define __ardour_image_comp_h__ + +#include + +namespace ardourvis +{ + /** Simple version number */ + const int32_t MSG_VERSION = 1 ; + + /** the default port we use */ + const int32_t DEFAULT_PORT = 30000 ; + + /** the maximum buffer size we will use to send receive a message (image data handled differently) */ + const int32_t MAX_MSG_SIZE = 256 ; + + /** the number of characters used for a value describing the characters within a textual data element */ + const int32_t TEXT_SIZE_CHARS = 3 ; + + /** the number of characters we use for time values within a message */ + const int32_t TIME_VALUE_CHARS = 10 ; + + /** the number of charachters we use for other value data, ie image width/height values */ + const int32_t IMAGE_SIZE_CHARS = 3 ; + + /** the number of characters used to for the size of the image data message */ + const int32_t IMAGE_DATA_MESSAGE_SIZE_CHARS = 32 ; + + // ------------------------------------------------------------------------- // + // Main Actions + // we join the action chars with items to create the message + // with the exception of the return values, all messages begin with one + // of these message parts + + /** Insert an Item */ + const std::string INSERT_ITEM = "IN" ; + + /** Remove an Item */ + const std::string REMOVE_ITEM = "RM" ; + + /** Rename a named item */ + const std::string RENAME_ITEM = "MV" ; + + /** Request some aditional data */ + const std::string REQUEST_DATA = "RQ" ; + + /** Return of a data request */ + const std::string RETURN_DATA = "RD" ; + + /** Update a item */ + const std::string ITEM_UPDATE = "IU" ; + + /** Select an Item */ + const std::string ITEM_SELECTED = "IS" ; + + /** Sesion Action */ + const std::string SESSION_ACTION = "SA" ; + + /** Sesion Action */ + const std::string SHUTDOWN = "SD" ; + + + // ------------------------------------------------------------------------- // + // Return values + const std::string RETURN_TRUE = "RT1" ; + const std::string RETURN_FALSE = "RT0" ; + + + + // ------------------------------------------------------------------------- // + // Updateable attributes + + /** Update the position of a time axis item */ + const std::string POSITION_CHANGE = "PC" ; + + /** Update the duration of a time axis item */ + const std::string DURATION_CHANGE = "DC" ; + + /** Enable the position lock constraint no a time axis item */ + const std::string POSITION_LOCK_CHANGE = "PL" ; + + /** Enable the duration lock constraint no a time axis item */ + const std::string DURATION_LOCK_CHANGE = "PL" ; + + /** Update the Maximum duration of a time axis item (_Upper _Duration) */ + const std::string MAX_DURATION_CHANGE = "UD" ; + + /** Enable the Maximum duration constraint of a time axis item (_Enable _Upper (Duration)) */ + const std::string MAX_DURATION_ENABLE_CHANGE = "EU" ; + + /** Update the Minimum duration of a time axis item (_Lowerr _Duration) */ + const std::string MIN_DURATION_CHANGE = "LD" ; + + /** Enable the Minimum duration constraint of a time axis item (_Enable _Lower (Duration)) */ + const std::string MIN_DURATION_ENABLE_CHANGE = "EL" ; + + /** Refresh the image data of an imageframe item (original image has been altered?) */ + const std::string IMAGE_REFRESH = "IR" ; + + /** the session sample rate has changed */ + const std::string SAMPLE_RATE_CHANGE = "RC" ; + + + + // ------------------------------------------------------------------------- // + // Requestable data items + + /** RGB data of the iamge */ + // this is probably a bad choice of string ! + const std::string IMAGE_RGB_DATA = "ID" ; + + /** the (path) name of the Ardour session */ + const std::string SESSION_NAME = "SN" ; + + /** the current sample rate */ + const std::string SAMPLE_RATE = "SR" ; + + /** the (path) name of the image compositor session */ + const std::string COMPOSITOR_SESSION = "CS" ; + + + // ------------------------------------------------------------------------- // + // Session Actions - follwed by session path + + /** Close a session */ + const std::string CLOSE_SESSION = "CS" ; + + /** Open a session */ + const std::string OPEN_SESSION = "OS" ; + + + + // ------------------------------------------------------------------------- // + // Items + + const std::string IMAGEFRAME_TIME_AXIS = "IT" ; + const std::string MARKER_TIME_AXIS = "MT" ; + const std::string IMAGEFRAME_ITEM = "II" ; + const std::string MARKER_ITEM = "MI" ; + + /** or an ImageFrameTimeAxisGroup */ + const std::string IMAGEFRAME_GROUP = "IG" ; + +} /* namespace ardour_visual */ + +#endif /* __ardour_image_comp_socket_h__ */ diff --git a/gtk2_ardour/ardour_message.cc b/gtk2_ardour/ardour_message.cc new file mode 100644 index 0000000000..52b7ab567c --- /dev/null +++ b/gtk2_ardour/ardour_message.cc @@ -0,0 +1,73 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ + +*/ + +#include "ardour_message.h" +#include "i18n.h" + +using namespace std; +using namespace Gtk; + + +ArdourMessage::ArdourMessage (Gtk::Window* parent, + string name, string msg, + bool grab_focus, bool auto_run) + : ArdourDialog (name), + ok_button (_("OK")) +{ + set_keyboard_input (true); + + label.set_text (msg); + label.set_alignment (0.5, 0.5); + label.set_name (X_("PrompterLabel")); + + ok_button.set_name ("EditorGTKButton"); + ok_button.clicked.connect (bind (slot (*this, &ArdourDialog::stop), 1)); + + packer.set_spacing (10); + packer.set_border_width (10); + packer.pack_start (label); + packer.pack_start (ok_button); + + set_name (X_("Prompter")); + set_position (GTK_WIN_POS_MOUSE); + set_modal (true); + add (packer); + show_all (); + + realize(); + get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + + if (grab_focus) { + ok_button.grab_focus (); + } + + if (parent) { + set_transient_for (*parent); + } + + if (auto_run) { + run (); + } +} + +ArdourMessage::~ArdourMessage() +{ +} diff --git a/gtk2_ardour/ardour_message.h b/gtk2_ardour/ardour_message.h new file mode 100644 index 0000000000..11f4c09340 --- /dev/null +++ b/gtk2_ardour/ardour_message.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ + +*/ + +#ifndef __ardour_message_h__ +#define __ardour_message_h__ + +#include + +#include +#include +#include + +#include "ardour_dialog.h" + +class ArdourMessage : public ArdourDialog +{ + public: + ArdourMessage (Gtk::Window* parent, + std::string name, std::string msg, + bool grabfocus = true, + bool autorun = true); + ~ArdourMessage(); + + private: + Gtk::VBox packer; + Gtk::Button ok_button; + Gtk::Label label; + +}; + +#endif // __ardour_message_h__ diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc new file mode 100644 index 0000000000..1dcada4a7c --- /dev/null +++ b/gtk2_ardour/ardour_ui.cc @@ -0,0 +1,3385 @@ +/* + Copyright (C) 1999-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ardour_ui.h" +#include "ardour_message.h" +#include "public_editor.h" +#include "audio_clock.h" +#include "keyboard.h" +#include "mixer_ui.h" +#include "prompter.h" +#include "opts.h" +#include "keyboard_target.h" +#include "add_route_dialog.h" +#include "new_session_dialog.h" +#include "about.h" +#include "utils.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtkmmext; +using namespace Gtk; +using namespace SigC; + +ARDOUR_UI *ARDOUR_UI::theArdourUI = 0; +SoundFileSelector* ARDOUR_UI::sfdb_window = 0; + +SigC::Signal1 ARDOUR_UI::Blink; +SigC::Signal0 ARDOUR_UI::RapidScreenUpdate; +SigC::Signal0 ARDOUR_UI::SuperRapidScreenUpdate; +SigC::Signal1 ARDOUR_UI::Clock; + +/* XPM */ +static const gchar *h_meter_strip_xpm[] = { +"186 5 187 2", +" c None", +". c #2BFE00", +"+ c #2DFE00", +"@ c #2FFE01", +"# c #32FE01", +"$ c #34FE02", +"% c #36FE02", +"& c #38FE03", +"* c #3BFE03", +"= c #3DFD04", +"- c #3FFD04", +"; c #41FD05", +"> c #44FD05", +", c #46FD06", +"' c #48FD06", +") c #4AFD07", +"! c #4DFD07", +"~ c #4FFD08", +"{ c #51FC08", +"] c #53FC09", +"^ c #56FC09", +"/ c #58FC09", +"( c #5AFC0A", +"_ c #5CFC0A", +": c #5FFC0B", +"< c #61FC0B", +"[ c #63FB0C", +"} c #65FB0C", +"| c #68FB0D", +"1 c #6AFB0D", +"2 c #6CFB0E", +"3 c #6EFB0E", +"4 c #71FB0F", +"5 c #73FB0F", +"6 c #75FB10", +"7 c #77FA10", +"8 c #7AFA11", +"9 c #7CFA11", +"0 c #7EFA12", +"a c #80FA12", +"b c #83FA12", +"c c #85FA13", +"d c #87FA13", +"e c #89FA14", +"f c #8CF914", +"g c #8EF915", +"h c #90F915", +"i c #92F916", +"j c #95F916", +"k c #97F917", +"l c #99F917", +"m c #9BF918", +"n c #9EF818", +"o c #A0F819", +"p c #A2F819", +"q c #A4F81A", +"r c #A7F81A", +"s c #A9F81A", +"t c #ABF81B", +"u c #ADF81B", +"v c #B0F81C", +"w c #B2F71C", +"x c #B4F71D", +"y c #B6F71D", +"z c #B9F71E", +"A c #BBF71E", +"B c #BDF71F", +"C c #BFF71F", +"D c #C2F720", +"E c #C4F720", +"F c #C6F621", +"G c #C8F621", +"H c #CBF622", +"I c #CDF622", +"J c #CFF623", +"K c #D1F623", +"L c #D4F624", +"M c #D6F624", +"N c #D8F524", +"O c #DAF525", +"P c #DDF525", +"Q c #DFF526", +"R c #E1F526", +"S c #E3F527", +"T c #E6F527", +"U c #E8F528", +"V c #EAF528", +"W c #ECF429", +"X c #EFF429", +"Y c #F1F42A", +"Z c #F3F42A", +"` c #F5F42B", +" . c #F8F42B", +".. c #FAF42C", +"+. c #FCF42C", +"@. c #FFF42D", +"#. c #FFF22C", +"$. c #FFF12B", +"%. c #FFF02A", +"&. c #FFEF2A", +"*. c #FFEE29", +"=. c #FFED28", +"-. c #FFEC28", +";. c #FFEB27", +">. c #FFE926", +",. c #FFE826", +"'. c #FFE725", +"). c #FFE624", +"!. c #FFE524", +"~. c #FFE423", +"{. c #FFE322", +"]. c #FFE222", +"^. c #FFE021", +"/. c #FFDF20", +"(. c #FFDE20", +"_. c #FFDD1F", +":. c #FFDC1E", +"<. c #FFDB1E", +"[. c #FFDA1D", +"}. c #FFD91C", +"|. c #FFD71B", +"1. c #FFD61B", +"2. c #FFD51A", +"3. c #FFD419", +"4. c #FFD319", +"5. c #FFD218", +"6. c #FFD117", +"7. c #FFD017", +"8. c #FFCF16", +"9. c #FFCD15", +"0. c #FFCC15", +"a. c #FFCB14", +"b. c #FFCA13", +"c. c #FFC913", +"d. c #FFC812", +"e. c #FFC711", +"f. c #FFC611", +"g. c #FFC410", +"h. c #FFC30F", +"i. c #FFC20F", +"j. c #FFC10E", +"k. c #FFC00D", +"l. c #FFBF0C", +"m. c #FFBE0C", +"n. c #FFBD0B", +"o. c #FFBB0A", +"p. c #FFBA0A", +"q. c #FFB909", +"r. c #FFB808", +"s. c #FFB708", +"t. c #FFB607", +"u. c #FFB506", +"v. c #FFB406", +"w. c #FFB205", +"x. c #FFB104", +"y. c #FFB004", +"z. c #FFAF03", +"A. c #FFAE02", +"B. c #FFAD02", +"C. c #FFAC01", +"D. c #FFAB00", +"E. c #FFA900", +"F. c #F11F00", +"G. c #F21E00", +"H. c #F21C00", +"I. c #F31B00", +"J. c #F31A00", +"K. c #F41800", +"L. c #F41700", +"M. c #F51600", +"N. c #F61400", +"O. c #F61300", +"P. c #F71100", +"Q. c #F71000", +"R. c #F80F00", +"S. c #F90D00", +"T. c #F90C00", +"U. c #FA0B00", +"V. c #FA0900", +"W. c #FB0800", +"X. c #FC0600", +"Y. c #FC0500", +"Z. c #FD0400", +"`. c #FD0200", +" + c #FE0100", +".+ c #FE0000", +"++ c #FF0000", +". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+", +". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +.+", +". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++", +". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++", +". + @ # $ % & * = - ; > , ' ) ! ~ { ] ^ / ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ` ...+.@.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.`. +++"}; + +/* XPM */ +static const gchar * v_meter_strip_xpm[] = { +"5 250 230 2", +" c None", +". c #FE0000", +"+ c #FF0000", +"@ c #FE0100", +"# c #FD0200", +"$ c #FD0300", +"% c #FD0400", +"& c #FC0500", +"* c #FC0600", +"= c #FC0700", +"- c #FB0800", +"; c #FA0900", +"> c #FA0A00", +", c #FA0B00", +"' c #F90C00", +") c #F90D00", +"! c #F80E00", +"~ c #F80F00", +"{ c #F71000", +"] c #F71100", +"^ c #F61200", +"/ c #F61300", +"( c #F61400", +"_ c #F51600", +": c #F41700", +"< c #F41800", +"[ c #F31A00", +"} c #F31B00", +"| c #F21C00", +"1 c #F21E00", +"2 c #F11F00", +"3 c #F54A00", +"4 c #FFA900", +"5 c #FFAB00", +"6 c #FFAC01", +"7 c #FFAD02", +"8 c #FFAE02", +"9 c #FFAF03", +"0 c #FFB004", +"a c #FFB104", +"b c #FFB205", +"c c #FFB406", +"d c #FFB506", +"e c #FFB607", +"f c #FFB708", +"g c #FFB808", +"h c #FFB909", +"i c #FFBA0A", +"j c #FFBB0A", +"k c #FFBC0A", +"l c #FFBD0B", +"m c #FFBE0C", +"n c #FFBF0C", +"o c #FFC00D", +"p c #FFC10E", +"q c #FFC20F", +"r c #FFC30F", +"s c #FFC410", +"t c #FFC511", +"u c #FFC611", +"v c #FFC711", +"w c #FFC812", +"x c #FFC913", +"y c #FFCA13", +"z c #FFCB14", +"A c #FFCC15", +"B c #FFCD15", +"C c #FFCF16", +"D c #FFD017", +"E c #FFD117", +"F c #FFD218", +"G c #FFD319", +"H c #FFD419", +"I c #FFD51A", +"J c #FFD61B", +"K c #FFD71B", +"L c #FFD81C", +"M c #FFD91C", +"N c #FFDA1D", +"O c #FFDB1E", +"P c #FFDC1E", +"Q c #FFDD1F", +"R c #FFDE20", +"S c #FFDF20", +"T c #FFE021", +"U c #FFE222", +"V c #FFE322", +"W c #FFE423", +"X c #FFE524", +"Y c #FFE624", +"Z c #FFE725", +"` c #FFE826", +" . c #FFE926", +".. c #FFEA26", +"+. c #FFEB27", +"@. c #FFEC28", +"#. c #FFED28", +"$. c #FFEE29", +"%. c #FFEF2A", +"&. c #FFF02A", +"*. c #FFF12B", +"=. c #FFF22C", +"-. c #FFF32D", +";. c #FFF42D", +">. c #FDF42C", +",. c #FBF42C", +"'. c #FAF42C", +"). c #F8F42B", +"!. c #F6F42B", +"~. c #F4F42B", +"{. c #F3F42A", +"]. c #F1F42A", +"^. c #F0F429", +"/. c #EEF429", +"(. c #ECF429", +"_. c #EAF528", +":. c #E9F528", +"<. c #E7F528", +"[. c #E5F527", +"}. c #E3F527", +"|. c #E2F526", +"1. c #E0F526", +"2. c #DFF526", +"3. c #DDF525", +"4. c #DBF525", +"5. c #D9F525", +"6. c #D8F524", +"7. c #D6F624", +"8. c #D5F624", +"9. c #D3F624", +"0. c #D1F623", +"a. c #CFF623", +"b. c #CEF622", +"c. c #CCF622", +"d. c #CBF622", +"e. c #C9F621", +"f. c #C7F621", +"g. c #C5F621", +"h. c #C4F720", +"i. c #C2F720", +"j. c #C0F71F", +"k. c #BEF71F", +"l. c #BDF71F", +"m. c #BBF71E", +"n. c #BAF71E", +"o. c #B8F71E", +"p. c #B6F71D", +"q. c #B5F71D", +"r. c #B3F71D", +"s. c #B2F71C", +"t. c #B0F81C", +"u. c #AEF81B", +"v. c #ACF81B", +"w. c #ABF81B", +"x. c #A9F81A", +"y. c #A8F81A", +"z. c #A6F81A", +"A. c #A4F81A", +"B. c #A2F819", +"C. c #A1F819", +"D. c #9FF819", +"E. c #9EF818", +"F. c #9BF918", +"G. c #9AF917", +"H. c #98F917", +"I. c #97F917", +"J. c #95F916", +"K. c #93F916", +"L. c #91F916", +"M. c #90F915", +"N. c #8EF915", +"O. c #8DF914", +"P. c #8BF914", +"Q. c #89FA14", +"R. c #87FA13", +"S. c #86FA13", +"T. c #84FA13", +"U. c #83FA12", +"V. c #81FA12", +"W. c #7FFA12", +"X. c #7DFA12", +"Y. c #7CFA11", +"Z. c #7AFA11", +"`. c #78FA10", +" + c #76FA10", +".+ c #75FB10", +"++ c #73FB0F", +"@+ c #72FB0F", +"#+ c #70FB0F", +"$+ c #6EFB0E", +"%+ c #6DFB0E", +"&+ c #6BFB0E", +"*+ c #6AFB0D", +"=+ c #68FB0D", +"-+ c #66FB0C", +";+ c #64FB0C", +">+ c #63FB0C", +",+ c #61FC0B", +"'+ c #60FC0B", +")+ c #5EFC0B", +"!+ c #5CFC0A", +"~+ c #5AFC0A", +"{+ c #59FC09", +"]+ c #57FC09", +"^+ c #56FC09", +"/+ c #53FC09", +"(+ c #52FC08", +"_+ c #50FC08", +":+ c #4FFD08", +"<+ c #4DFD07", +"[+ c #4BFD07", +"}+ c #49FD07", +"|+ c #48FD06", +"1+ c #46FD06", +"2+ c #45FD05", +"3+ c #43FD05", +"4+ c #41FD05", +"5+ c #3FFD04", +"6+ c #3EFD04", +"7+ c #3CFD04", +"8+ c #3BFE03", +"9+ c #39FE03", +"0+ c #37FE02", +"a+ c #35FE02", +"b+ c #34FE02", +"c+ c #32FE01", +"d+ c #30FE01", +"e+ c #2EFE01", +"f+ c #2DFE00", +"g+ c #2BFE00", +". . + + + ", +". . + + + ", +"@ @ @ @ @ ", +"# # # # # ", +"$ $ $ $ $ ", +"% % % % % ", +"& & & & & ", +"* * * * * ", +"= = = = = ", +"- - - - - ", +"; ; ; ; ; ", +"> > > > > ", +", , , , , ", +"' ' ' ' ' ", +") ) ) ) ) ", +"! ! ! ! ! ", +"~ ~ ~ ~ ~ ", +"{ { { { { ", +"] ] ] ] ] ", +"^ ^ ^ ^ ^ ", +"/ / / / / ", +"( ( ( ( ( ", +"_ _ _ _ _ ", +": : : : : ", +": : : : : ", +"< < < < < ", +"[ [ [ [ [ ", +"} } } } } ", +"} } } } } ", +"| | | | | ", +"1 1 1 1 1 ", +"2 2 2 2 2 ", +"3 3 3 3 3 ", +"4 4 4 4 4 ", +"5 5 5 5 5 ", +"6 6 6 6 6 ", +"6 6 6 6 6 ", +"7 7 7 7 7 ", +"8 8 8 8 8 ", +"9 9 9 9 9 ", +"9 9 9 9 9 ", +"0 0 0 0 0 ", +"a a a a a ", +"a a a a a ", +"b b b b b ", +"c c c c c ", +"d d d d d ", +"d d d d d ", +"e e e e e ", +"f f f f f ", +"g g g g g ", +"g g g g g ", +"h h h h h ", +"i i i i i ", +"j j j j j ", +"k k k k k ", +"l l l l l ", +"m m m m m ", +"n n n n n ", +"n n n n n ", +"o o o o o ", +"p p p p p ", +"q q q q q ", +"q q q q q ", +"r r r r r ", +"s s s s s ", +"t t t t t ", +"u u u u u ", +"v v v v v ", +"w w w w w ", +"x x x x x ", +"x x x x x ", +"y y y y y ", +"z z z z z ", +"A A A A A ", +"A A A A A ", +"B B B B B ", +"C C C C C ", +"D D D D D ", +"D D D D D ", +"E E E E E ", +"F F F F F ", +"G G G G G ", +"G G G G G ", +"H H H H H ", +"I I I I I ", +"I I I I I ", +"J J J J J ", +"K K K K K ", +"L L L L L ", +"M M M M M ", +"N N N N N ", +"O O O O O ", +"P P P P P ", +"P P P P P ", +"Q Q Q Q Q ", +"R R R R R ", +"S S S S S ", +"S S S S S ", +"T T T T T ", +"U U U U U ", +"V V V V V ", +"V V V V V ", +"W W W W W ", +"X X X X X ", +"Y Y Y Y Y ", +"Y Y Y Y Y ", +"Z Z Z Z Z ", +"` ` ` ` ` ", +" . . . . .", +"..........", +"+.+.+.+.+.", +"@.@.@.@.@.", +"#.#.#.#.#.", +"#.#.#.#.#.", +"$.$.$.$.$.", +"%.%.%.%.%.", +"&.&.&.&.&.", +"&.&.&.&.&.", +"*.*.*.*.*.", +"=.=.=.=.=.", +"-.-.-.-.-.", +";.;.;.;.;.", +";.;.;.;.;.", +">.>.>.>.>.", +",.,.,.,.,.", +"'.'.'.'.'.", +").).).).).", +"!.!.!.!.!.", +"~.~.~.~.~.", +"{.{.{.{.{.", +"].].].].].", +"^.^.^.^.^.", +"/././././.", +"(.(.(.(.(.", +"_._._._._.", +":.:.:.:.:.", +"<.<.<.<.<.", +"[.[.[.[.[.", +"}.}.}.}.}.", +"|.|.|.|.|.", +"1.1.1.1.1.", +"2.2.2.2.2.", +"3.3.3.3.3.", +"4.4.4.4.4.", +"5.5.5.5.5.", +"6.6.6.6.6.", +"7.7.7.7.7.", +"8.8.8.8.8.", +"9.9.9.9.9.", +"0.0.0.0.0.", +"a.a.a.a.a.", +"b.b.b.b.b.", +"c.c.c.c.c.", +"d.d.d.d.d.", +"e.e.e.e.e.", +"f.f.f.f.f.", +"g.g.g.g.g.", +"h.h.h.h.h.", +"i.i.i.i.i.", +"j.j.j.j.j.", +"k.k.k.k.k.", +"l.l.l.l.l.", +"m.m.m.m.m.", +"n.n.n.n.n.", +"o.o.o.o.o.", +"p.p.p.p.p.", +"q.q.q.q.q.", +"r.r.r.r.r.", +"s.s.s.s.s.", +"t.t.t.t.t.", +"u.u.u.u.u.", +"v.v.v.v.v.", +"w.w.w.w.w.", +"x.x.x.x.x.", +"y.y.y.y.y.", +"z.z.z.z.z.", +"A.A.A.A.A.", +"B.B.B.B.B.", +"C.C.C.C.C.", +"D.D.D.D.D.", +"E.E.E.E.E.", +"F.F.F.F.F.", +"G.G.G.G.G.", +"H.H.H.H.H.", +"I.I.I.I.I.", +"J.J.J.J.J.", +"K.K.K.K.K.", +"L.L.L.L.L.", +"M.M.M.M.M.", +"N.N.N.N.N.", +"O.O.O.O.O.", +"P.P.P.P.P.", +"Q.Q.Q.Q.Q.", +"R.R.R.R.R.", +"S.S.S.S.S.", +"T.T.T.T.T.", +"U.U.U.U.U.", +"V.V.V.V.V.", +"W.W.W.W.W.", +"X.X.X.X.X.", +"Y.Y.Y.Y.Y.", +"Z.Z.Z.Z.Z.", +"`.`.`.`.`.", +" + + + + +", +".+.+.+.+.+", +"++++++++++", +"@+@+@+@+@+", +"#+#+#+#+#+", +"$+$+$+$+$+", +"%+%+%+%+%+", +"&+&+&+&+&+", +"*+*+*+*+*+", +"=+=+=+=+=+", +"-+-+-+-+-+", +";+;+;+;+;+", +">+>+>+>+>+", +",+,+,+,+,+", +"'+'+'+'+'+", +")+)+)+)+)+", +"!+!+!+!+!+", +"~+~+~+~+~+", +"{+{+{+{+{+", +"]+]+]+]+]+", +"^+^+^+^+^+", +"/+/+/+/+/+", +"(+(+(+(+(+", +"_+_+_+_+_+", +":+:+:+:+:+", +"<+<+<+<+<+", +"[+[+[+[+[+", +"}+}+}+}+}+", +"|+|+|+|+|+", +"1+1+1+1+1+", +"2+2+2+2+2+", +"3+3+3+3+3+", +"4+4+4+4+4+", +"5+5+5+5+5+", +"6+6+6+6+6+", +"7+7+7+7+7+", +"8+8+8+8+8+", +"9+9+9+9+9+", +"0+0+0+0+0+", +"a+a+a+a+a+", +"b+b+b+b+b+", +"c+c+c+c+c+", +"d+d+d+d+d+", +"e+e+e+e+e+", +"f+f+f+f+f+", +"g+g+g+g+g+"}; + +static const char* channel_setup_names[] = { + "mono", + "stereo", + "3 channels", + "4 channels", + "5 channels", + "8 channels", + "manual setup", + 0 +}; + +vector channel_combo_strings; + +ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], string rcfile) + + : Gtkmmext::UI ("ardour", argcp, argvp, rcfile), + + primary_clock (X_("TransportClockDisplay"), true, false, true), + secondary_clock (X_("SecondaryClockDisplay"), true, false, true), + preroll_clock (X_("PreRollClock"), true, true), + postroll_clock (X_("PostRollClock"), true, true), + + /* adjuster table */ + + adjuster_table (3, 3), + + /* preroll stuff */ + + preroll_button (_("pre\nroll")), + postroll_button (_("post\nroll")), + + /* big clock */ + + big_clock ("BigClockDisplay", true), + + /* transport */ + + shuttle_units_button (_("% ")), + shuttle_style_button (_("spring")), + + punch_in_button (_("punch\nin")), + punch_out_button (_("punch\nout")), + auto_return_button (_("auto\nreturn")), + auto_play_button (_("auto\nplay")), + auto_input_button (_("auto\ninput")), + click_button (_("click")), + follow_button (_("follow\nPH")), + auditioning_alert_button (_("AUDITIONING")), + solo_alert_button (_("SOLO")), + + session_selector (1, 0), + + shown_flag (false) + +{ + using namespace Gtk::Menu_Helpers; + + Gtkmmext::init(); + + /* actually, its already loaded, but ... */ + + cerr << "Loading UI configuration file " << rcfile << endl; + + about = 0; + + if (theArdourUI == 0) { + theArdourUI = this; + } + + editor = 0; + mixer = 0; + session = 0; + _session_is_new = false; + big_clock_window = 0; + session_selector_window = 0; + last_key_press_time = 0; + connection_editor = 0; + add_route_dialog = 0; + route_params = 0; + meter_bridge = 0; + option_editor = 0; + location_ui = 0; + sfdb_window = 0; + new_session_window = 0; + open_session_selector = 0; + have_configure_timeout = false; + have_disk_overrun_displayed = false; + have_disk_underrun_displayed = false; + _will_create_new_session_automatically = false; + session_loaded = false; + + last_configure_time.tv_sec = 0; + last_configure_time.tv_usec = 0; + + shuttle_grabbed = false; + shuttle_fract = 0.0; + + set_shuttle_units (Percentage); + set_shuttle_behaviour (Sprung); + + shuttle_unit_menu.items().push_back (MenuElem (_("Percentage"), bind (slot (*this, &ARDOUR_UI::set_shuttle_units), + Percentage))); + shuttle_unit_menu.items().push_back (MenuElem (_("Semitones"), bind (slot (*this, &ARDOUR_UI::set_shuttle_units), + Semitones))); + + shuttle_style_menu.items().push_back (MenuElem (_("Sprung"), bind (slot (*this, &ARDOUR_UI::set_shuttle_behaviour), + Sprung))); + shuttle_style_menu.items().push_back (MenuElem (_("Wheel"), bind (slot (*this, &ARDOUR_UI::set_shuttle_behaviour), + Wheel))); + + gettimeofday (&last_peak_grab, 0); + gettimeofday (&last_shuttle_request, 0); + + ARDOUR::DiskStream::CannotRecordNoInput.connect (slot (*this, &ARDOUR_UI::cannot_record_no_input)); + ARDOUR::DiskStream::DeleteSources.connect (slot (*this, &ARDOUR_UI::delete_sources_in_the_right_thread)); + ARDOUR::DiskStream::DiskOverrun.connect (slot (*this, &ARDOUR_UI::disk_overrun_handler)); + ARDOUR::DiskStream::DiskUnderrun.connect (slot (*this, &ARDOUR_UI::disk_underrun_handler)); + + /* handle pending state with a dialog */ + + ARDOUR::Session::AskAboutPendingState.connect (slot (*this, &ARDOUR_UI::pending_state_dialog)); + + channel_combo_strings = internationalize (channel_setup_names); + + /* have to wait for AudioEngine and Configuration before proceeding */ +} + +void +ARDOUR_UI::cannot_record_no_input (DiskStream* ds) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &ARDOUR_UI::cannot_record_no_input), ds)); + + string msg = compose (_("\ +You cannot record-enable\n\ +track %1\n\ +because it has no input connections.\n\ +You would be wasting space recording silence."), + ds->name()); + + ArdourMessage message (editor, X_("cannotrecord"), msg); +} + +void +ARDOUR_UI::set_engine (AudioEngine& e) +{ + engine = &e; + + engine->Stopped.connect (slot (*this, &ARDOUR_UI::engine_stopped)); + engine->Running.connect (slot (*this, &ARDOUR_UI::engine_running)); + engine->Halted.connect (slot (*this, &ARDOUR_UI::engine_halted)); + engine->SampleRateChanged.connect (slot (*this, &ARDOUR_UI::update_sample_rate)); + + _tooltips.enable(); + + keyboard = new Keyboard; + install_keybindings (); + + FastMeter::set_vertical_xpm (v_meter_strip_xpm); + FastMeter::set_horizontal_xpm (h_meter_strip_xpm); + + if (setup_windows ()) { + throw failed_constructor (); + } + + if (GTK_ARDOUR::show_key_actions) { + KeyboardTarget::show_all_actions (); + exit (0); + } + + /* start with timecode, metering enabled + */ + + blink_timeout_tag = -1; + + /* this being a GUI and all, we want peakfiles */ + + FileSource::set_build_peakfiles (true); + FileSource::set_build_missing_peakfiles (true); + + if (Source::start_peak_thread ()) { + throw failed_constructor(); + } + + /* start the time-of-day-clock */ + + update_wall_clock (); + Main::timeout.connect (slot (*this, &ARDOUR_UI::update_wall_clock), 60000); + + update_disk_space (); + update_cpu_load (); + update_sample_rate (engine->frame_rate()); + + starting.connect (slot (*this, &ARDOUR_UI::startup)); + stopping.connect (slot (*this, &ARDOUR_UI::shutdown)); +} + +ARDOUR_UI::~ARDOUR_UI () +{ + save_ardour_state (); + + if (keyboard) { + delete keyboard; + } + + if (editor) { + delete editor; + } + + if (mixer) { + delete mixer; + } + + if (add_route_dialog) { + delete add_route_dialog; + } + + Source::stop_peak_thread (); +} + +gint +ARDOUR_UI::configure_timeout () +{ + struct timeval now; + struct timeval diff; + + if (last_configure_time.tv_sec == 0 && last_configure_time.tv_usec == 0) { + /* no configure events yet */ + return TRUE; + } + + gettimeofday (&now, 0); + timersub (&now, &last_configure_time, &diff); + + /* force a gap of 0.5 seconds since the last configure event + */ + + if (diff.tv_sec == 0 && diff.tv_usec < 500000) { + return TRUE; + } else { + have_configure_timeout = false; + save_ardour_state (); + return FALSE; + } +} + +gboolean +ARDOUR_UI::configure_handler (GdkEventConfigure* conf) +{ + if (have_configure_timeout) { + gettimeofday (&last_configure_time, 0); + } else { + TimeoutSig t; + t.connect (slot (*this, &ARDOUR_UI::configure_timeout), 100); + have_configure_timeout = true; + } + + return FALSE; +} + +void +ARDOUR_UI::save_ardour_state () +{ + if (!keyboard || !mixer || !editor) { + return; + } + + /* XXX this is all a bit dubious. add_extra_xml() uses + a different lifetime model from add_instant_xml(). + */ + + XMLNode* node = new XMLNode (keyboard->get_state()); + Config->add_extra_xml (*node); + Config->save_state(); + + XMLNode& enode (static_cast(editor)->get_state()); + XMLNode& mnode (mixer->get_state()); + + if (session) { + session->add_instant_xml(enode, session->path()); + session->add_instant_xml(mnode, session->path()); + } else { + Config->add_instant_xml(enode, Config->get_user_ardour_path()); + Config->add_instant_xml(mnode, Config->get_user_ardour_path()); + } +} + +void +ARDOUR_UI::startup () +{ + /* Once the UI is up and running, start the audio engine. Doing + this before the UI is up and running can cause problems + when not running with SCHED_FIFO, because the amount of + CPU and disk work needed to get the UI started can interfere + with the scheduling of the audio thread. + */ + + Gtk::Main::idle.connect (slot (*this, &ARDOUR_UI::start_engine)); +} + +void +ARDOUR_UI::finish() +{ + if (session && session->dirty()) { + switch (ask_about_saving_session(_("quit"))) { + case -1: + return; + break; + case 1: + /* use the default name */ + if (save_state_canfail ("")) { + /* failed - don't quit */ + ArdourMessage (editor, X_("badsave dialog"), + _("\ +Ardour was unable to save your session.\n\n\ +If you still wish to quit, please use the\n\n\ +\"Just quit\" option.")); + return; + } + break; + case 0: + break; + } + } + + quit(); +} + +int +ARDOUR_UI::ask_about_saving_session (string what) +{ + ArdourDialog window ("saving dialog"); + Gtk::VBox packer; + Gtk::Label prompt_label; + Gtk::HBox button_packer; + + string msg; + + msg = compose(_("Save and %1"), what); + + Gtk::Button save_button (msg); + save_button.set_name ("EditorGTKButton"); + + msg = compose(_("Just %1"), what); + + Gtk::Button nosave_button (msg); + nosave_button.set_name ("EditorGTKButton"); + + msg = compose(_("Don't %1"), what); + + Gtk::Button noquit_button (msg); + noquit_button.set_name ("EditorGTKButton"); + + string prompt; + string type; + + if (session->snap_name() == session->name()) { + type = _("session"); + } else { + type = _("snapshot"); + } + prompt = compose(_("The %1\n\"%2\"\nhas not been saved.\n\nAny changes made this time\nwill be lost unless you save it.\n\nWhat do you want to do?"), + type, session->snap_name()); + + prompt_label.set_text (prompt); + prompt_label.set_alignment (0.5, 0.5); + prompt_label.set_name (X_("PrompterLabel")); + + save_button.clicked.connect (bind(slot(window,&ArdourDialog::stop), 1)); + nosave_button.clicked.connect (bind(slot(window,&ArdourDialog::stop), 0)); + noquit_button.clicked.connect (bind(slot(window,&ArdourDialog::stop), -1)); + + button_packer.set_spacing (10); + button_packer.pack_start (save_button); + button_packer.pack_start (nosave_button); + button_packer.pack_start (noquit_button); + + packer.set_spacing (10); + packer.set_border_width (10); + packer.pack_start (prompt_label); + packer.pack_start (button_packer); + + window.set_name (_("Prompter")); + window.set_title (_("ardour: save session?")); + window.set_position (GTK_WIN_POS_MOUSE); + window.set_modal (true); + window.add (packer); + window.show_all (); + + window.realize(); + window.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + window.set_keyboard_input (true); + + save_the_session = 0; + + editor->ensure_float (window); + + window.run (); + + return window.run_status(); +} + +gint +ARDOUR_UI::every_second () +{ + update_cpu_load (); + update_buffer_load (); + update_disk_space (); + // update_disk_rate (); + return TRUE; +} + +gint +ARDOUR_UI::every_point_one_seconds () +{ + struct timeval now; + struct timeval diff; + + /* do not attempt to grab peak power more than once per cycle. + */ + + gettimeofday (&now, 0); + timersub (&now, &last_peak_grab, &diff); + + if ((diff.tv_usec + (diff.tv_sec * 1000000)) >= engine->usecs_per_cycle()) { + IO::GrabPeakPower(); /* EMIT_SIGNAL */ + last_peak_grab = now; + } + + update_speed_display (); + RapidScreenUpdate(); /* EMIT_SIGNAL */ + return TRUE; +} + +gint +ARDOUR_UI::every_point_zero_one_seconds () +{ + SuperRapidScreenUpdate(); /* EMIT_SIGNAL */ + return TRUE; +} + +void +ARDOUR_UI::update_sample_rate (jack_nframes_t ignored) +{ + char buf[32]; + + ENSURE_GUI_THREAD (bind (slot (*this, &ARDOUR_UI::update_sample_rate), ignored)); + + if (!engine->connected()) { + + snprintf (buf, sizeof (buf), _("disconnected")); + + } else { + + jack_nframes_t rate = engine->frame_rate(); + + if (fmod (rate, 1000.0) != 0.0) { + snprintf (buf, sizeof (buf), _("SR: %.1f kHz / %4.1f msecs"), + (float) rate/1000.0f, + (engine->frames_per_cycle() / (float) rate) * 1000.0f); + } else { + snprintf (buf, sizeof (buf), _("SR: %u kHz / %4.1f msecs"), + rate/1000, + (engine->frames_per_cycle() / (float) rate) * 1000.0f); + } + } + + sample_rate_label.set_text (buf); +} + +void +ARDOUR_UI::update_cpu_load () +{ + char buf[32]; + snprintf (buf, sizeof (buf), _("DSP Load: %.1f%%"), engine->get_cpu_load()); + cpu_load_label.set_text (buf); +} + +void +ARDOUR_UI::update_disk_rate () +{ + char buf[64]; + + if (session) { + snprintf (buf, sizeof (buf), _("Disk r:%5.1f w:%5.1f MB/s"), + session->read_data_rate()/1048576.0f, session->write_data_rate()/1048576.0f); + disk_rate_label.set_text (buf); + } else { + disk_rate_label.set_text (""); + } +} + +void +ARDOUR_UI::update_buffer_load () +{ + char buf[64]; + + if (session) { + snprintf (buf, sizeof (buf), _("Buffers p:%" PRIu32 "%% c:%" PRIu32 "%%"), + session->playback_load(), session->capture_load()); + buffer_load_label.set_text (buf); + } else { + buffer_load_label.set_text (""); + } +} + +void +ARDOUR_UI::count_recenabled_diskstreams (DiskStream& ds) +{ + if (ds.record_enabled()) { + rec_enabled_diskstreams++; + } +} + +void +ARDOUR_UI::update_disk_space() +{ + if (session == 0) { + return; + } + + jack_nframes_t frames = session->available_capture_duration(); + char buf[64]; + + if (frames == max_frames) { + strcpy (buf, _("space: 24hrs+")); + } else { + int hrs; + int mins; + int secs; + jack_nframes_t fr = session->frame_rate(); + + if (session->actively_recording()){ + + rec_enabled_diskstreams = 0; + session->foreach_diskstream (this, &ARDOUR_UI::count_recenabled_diskstreams); + + if (rec_enabled_diskstreams) { + frames /= rec_enabled_diskstreams; + } + + } else { + + /* hmmm. shall we divide by the route count? or the diskstream count? + or what? for now, do nothing ... + */ + + } + + hrs = frames / (fr * 3600); + frames -= hrs * fr * 3600; + mins = frames / (fr * 60); + frames -= mins * fr * 60; + secs = frames / fr; + + snprintf (buf, sizeof(buf), _("space: %02dh:%02dm:%02ds"), hrs, mins, secs); + } + + disk_space_label.set_text (buf); +} + +gint +ARDOUR_UI::update_wall_clock () +{ + time_t now; + struct tm *tm_now; + char buf[16]; + + time (&now); + tm_now = localtime (&now); + + sprintf (buf, "%02d:%02d", tm_now->tm_hour, tm_now->tm_min); + wall_clock_label.set_text (buf); + + return TRUE; +} + +void +ARDOUR_UI::toggle_recording_plugins () +{ + /* XXX use toggle_some_session_state */ + + if (session == 0) { + return; + } + + session->set_recording_plugins (!session->get_recording_plugins()); +} + +void +ARDOUR_UI::toggle_auto_play () + +{ + toggle_some_session_state (auto_play_button, + &Session::get_auto_play, + &Session::set_auto_play); +} + +void +ARDOUR_UI::toggle_auto_return () + +{ + toggle_some_session_state (auto_return_button, + &Session::get_auto_return, + &Session::set_auto_return); +} + +void +ARDOUR_UI::toggle_click () +{ + toggle_some_session_state (click_button, + &Session::get_clicking, + &Session::set_clicking); +} + +void +ARDOUR_UI::follow_changed () +{ + bool x; + + if (!editor) { + return; + } + + if (follow_button.get_active() != (x = editor->follow_playhead())) { + follow_button.set_active (x); + } +} + +void +ARDOUR_UI::toggle_follow () +{ + bool x; + + if (!editor) { + return; + } + + if (editor->follow_playhead() != (x = follow_button.get_active())) { + editor->set_follow_playhead (x); + } +} + +void +ARDOUR_UI::toggle_session_auto_loop () +{ + if (session) { + if (session->get_auto_loop()) { + if (session->transport_rolling()) { + transport_roll(); + } + else { + session->request_auto_loop (false); + } + } + else { + session->request_auto_loop (true); + } + } +} + +void +ARDOUR_UI::toggle_session_punch_in () +{ + if (session) { + session->set_punch_in (!session->get_punch_in()); + } +} + +void +ARDOUR_UI::toggle_punch_out () +{ + toggle_some_session_state (punch_out_button, + &Session::get_punch_out, + &Session::set_punch_out); +} + +void +ARDOUR_UI::toggle_punch_in () +{ + toggle_some_session_state (punch_in_button, + &Session::get_punch_in, + &Session::set_punch_in); +} + +void +ARDOUR_UI::map_button_state () + +{ + map_some_session_state (auto_return_button, + &Session::get_auto_return); + map_some_session_state (auto_play_button, + &Session::get_auto_play); + map_some_session_state (auto_input_button, + &Session::get_auto_input); + map_some_session_state (punch_in_button, + &Session::get_punch_in); + map_some_session_state (punch_out_button, + &Session::get_punch_out); + map_some_session_state (click_button, + &Session::get_clicking); +} + +void +ARDOUR_UI::queue_map_control_change (Session::ControlType t) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &ARDOUR_UI::map_control_change), t)); +} + +void +ARDOUR_UI::map_control_change (Session::ControlType t) +{ + switch (t) { + case Session::AutoPlay: + map_some_session_state (auto_play_button, &Session::get_auto_play); + break; + + case Session::AutoLoop: + break; + + case Session::AutoReturn: + map_some_session_state (auto_return_button, &Session::get_auto_return); + break; + + case Session::AutoInput: + map_some_session_state (auto_input_button, &Session::get_auto_input); + break; + + case Session::PunchOut: + map_some_session_state (punch_in_button, &Session::get_punch_out); + break; + + case Session::PunchIn: + map_some_session_state (punch_in_button, &Session::get_punch_in); + break; + + case Session::Clicking: + map_some_session_state (click_button, &Session::get_clicking); + break; + + case Session::SlaveType: +// map_some_session_state (mtc_slave_button, &Session::get_mtc_slave); + break; + + case Session::SendMTC: +// map_some_session_state (send_mtc_button, &Session::get_send_mtc); + break; + + case Session::SendMMC: +// map_some_session_state (send_mmc_button, &Session::get_send_mmc); + break; + + case Session::MMCControl: +// map_some_session_state (mmc_control_button, &Session::get_mmc_control); + break; + + case Session::MidiFeedback: +// map_some_session_state (mmc_control_button, &Session::get_mmc_control); + break; + case Session::MidiControl: +// map_some_session_state (mmc_control_button, &Session::get_mmc_control); + break; + + case Session::Live: + break; + + case Session::RecordingPlugins: + break; + + case Session::CrossFadesActive: + break; + + case Session::EditingMode: + break; + + case Session::PlayRange: + break; + + case Session::AlignChoice: + /* don't care, this is handled by the options editor */ + break; + case Session::SeamlessLoop: + /* don't care, this is handled by the options editor */ + break; + + } +} + +void +ARDOUR_UI::control_methods_adjusted () + +{ + int which_method; + + which_method = (int) online_control_button->adjustment.get_value(); + switch (which_method) { + case 0: + allow_mmc_and_local (); + break; + case 1: + allow_mmc_only (); + break; + case 2: + allow_local_only (); + break; + default: + fatal << _("programming error: impossible control method") << endmsg; + } +} + + +void +ARDOUR_UI::mmc_device_id_adjusted () + +{ +#if 0 + if (mmc) { + int dev_id = (int) mmc_id_button->adjustment.get_value(); + mmc->set_device_id (dev_id); + } +#endif +} + +void +ARDOUR_UI::map_some_session_state (ToggleButton& button, + bool (Session::*get)() const) + +{ + bool x; + + if (session == 0) { + return; + } + + if (button.get_active() != (x = (session->*get)())) { + button.set_active (x); + } +} + +void +ARDOUR_UI::toggle_some_session_state (ToggleButton& button, + bool (Session::*get)() const, + void (Session::*set)(bool)) + +{ + bool button_state; + bool session_state; + + if (session == 0) { + return; + } + + button_state = button.get_active (); + session_state = (session->*get)(); + + if (button_state != session_state) { + (session->*set) (button_state); +#if 0 + + /* check that it worked, and reverse + the button state if it didn't + */ + + if ((session->*get)() != button_state) { + button->set_active (!button_state); + } +#endif + + } +} + +gint +ARDOUR_UI::session_menu (GdkEventButton *ev) +{ + session_popup_menu->popup (0, 0, 0, 0); + return TRUE; +} + +void +ARDOUR_UI::redisplay_recent_sessions () +{ + using namespace Gtkmmext; + using namespace Gtk::CTree_Helpers; + + vector *sessions; + vector::iterator i; + RecentSessionsSorter cmp; + + /* ---------------------------------------- */ + /* XXX MAKE ME A FUNCTION (no CTree::clear() in gtkmm 1.2) */ + + gtk_ctree_remove_node (session_selector.gtkobj(), NULL); + /* ---------------------------------------- */ + + + RecentSessions rs; + ARDOUR::read_recent_sessions (rs); + + if (rs.empty()) { + session_selector.thaw(); + return; + } + /* sort them alphabetically */ + sort(rs.begin(), rs.end(), cmp); + sessions = new vector; + for (RecentSessions::iterator i = rs.begin(); i != rs.end(); ++i) { + sessions->push_back (new string ((*i).second)); + } + + session_selector.freeze(); + + for (i = sessions->begin(); i != sessions->end(); ++i) { + + vector* states; + vector item; + string fullpath = *(*i); + + /* remove any trailing / */ + + if (fullpath[fullpath.length()-1] == '/') { + fullpath = fullpath.substr (0, fullpath.length()-1); + } + + /* now get available states for this session */ + + if ((states = Session::possible_states(fullpath)) == 0) { + /* no state file? */ + continue; + } + + /* OK, try to add entries for this session */ + + + /* add the parent */ + + item.clear (); + string basen = PBD::basename (fullpath); + item.push_back (basen.c_str()); + session_selector.rows().push_back (Element (item)); + + session_selector.rows().back().set_data (new string (fullpath), deferred_delete); + + if (states->size() == 1) { + + /* only 1 state, show it at the top level */ + + session_selector.rows().back().set_leaf (true); + + } else { + + session_selector.rows().back().set_leaf (false); + + vector::iterator i2; + + /* add the children */ + + for (i2 = states->begin(); i2 != states->end(); ++i2) { + + string statename = *(*i2); + + item.clear (); + item.push_back (statename.c_str()); + + session_selector.rows().back().subtree().push_back (Element (item)); + session_selector.rows().back().subtree().back().set_data (new string (statename), + deferred_delete); + session_selector.rows().back().subtree().back().set_leaf (true); + + delete *i2; + } + } + + delete states; + } + + session_selector.thaw(); + delete sessions; +} + +void +ARDOUR_UI::session_selection (Gtk::CTree_Helpers::Row row, gint column) +{ + using namespace Gtk::CTree_Helpers; + + string session_name; + string session_path; + string session_state; + + if (!row.is_leaf()) { + row.expand(); + return; + } + + string *stp = static_cast (row.get_data()); + + if ((*stp)[0] != '/' && (*stp)[0] != '.') { + + /* its a state file node, so get the parent for the session information, + and combine with the state file name. + */ + + string *spp = static_cast (row.get_parent().get_data()); + + session_name = *spp; + session_path = *spp; + session_state = *stp; + + } else { + + /* its a session directory node, so just get the session path, + and use "default" to load the state. + */ + + string *spp = static_cast (row.get_data()); + + session_name = *spp; + session_path = *spp; + session_state = PBD::basename (*spp); + } + + session_selector_window->hide (); + _session_is_new = false; + load_session (session_path, session_state); +} + +void +ARDOUR_UI::build_session_selector () +{ + session_selector_window = new ArdourDialog ("session selector"); + + Gtk::VBox *vpacker = new Gtk::VBox; + Gtk::ScrolledWindow *scroller = new Gtk::ScrolledWindow; + Gtk::HBox *button_packer = new Gtk::HBox; + Gtk::Button *cancel_button = new Gtk::Button (_("cancel")); + Gtk::Button *rescan_button = new Gtk::Button (_("rescan")); + + button_packer->pack_start (*rescan_button); + button_packer->pack_start (*cancel_button); + + vpacker->pack_start (*scroller); + vpacker->pack_start (*button_packer, false, false); + + scroller->add (session_selector); + scroller->set_policy(GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + session_selector_window->add (*vpacker); + session_selector_window->set_name ("SessionSelectorWindow"); + session_selector_window->set_usize (200, 400); + + session_selector_window->delete_event.connect (bind (slot (just_hide_it), static_cast(session_selector_window))); + cancel_button->clicked.connect (bind (slot (*this, &ARDOUR_UI::hide_dialog), session_selector_window)); + session_selector.tree_select_row.connect (slot (*this, &ARDOUR_UI::session_selection)); +} + +void +ARDOUR_UI::fs_cancel_clicked (Gtk::FileSelection* fs) +{ + fs->hide_all(); + fs->get_selection_entry()->set_text(""); + allow_focus (false); +} + +gint +ARDOUR_UI::fs_delete_event (GdkEventAny* ev, Gtk::FileSelection* fs) +{ + fs_cancel_clicked (fs); + return 1; +} + +void +ARDOUR_UI::open_session () +{ + /* popup selector window */ + + if (open_session_selector == 0) { + open_session_selector = new Gtk::FileSelection(_("open session")); + open_session_selector->get_ok_button()->clicked.connect (slot (*this, &ARDOUR_UI::open_ok_clicked)); + open_session_selector->get_cancel_button()->clicked.connect (bind (slot (*this, &ARDOUR_UI::fs_cancel_clicked), open_session_selector)); + open_session_selector->delete_event.connect (bind (slot (*this, &ARDOUR_UI::fs_delete_event), open_session_selector)); + } + + open_session_selector->show_all (); + allow_focus (true); + + /* wait for selection */ +} + +void +ARDOUR_UI::open_ok_clicked () +{ + open_session_selector->hide_all(); + string session_path = open_session_selector->get_filename(); + string path, name; + bool isnew; + + if (session_path.length() > 0) { + if (Session::find_session (session_path, path, name, isnew) == 0) { + _session_is_new = isnew; + load_session (path, name); + } + } + + open_session_selector->get_selection_entry()->set_text(""); + + /* XXX hack hack hack */ + + GtkCList* clist = (GtkCList*) open_session_selector->gtkobj()->file_list; + gtk_clist_unselect_all (clist); + + allow_focus(false); +} + +void +ARDOUR_UI::open_recent_session () +{ + /* popup selector window */ + + if (session_selector_window == 0) { + build_session_selector (); + } + + redisplay_recent_sessions (); + session_selector_window->show_all (); + + /* wait for selection */ +} + +void +ARDOUR_UI::session_add_midi_track () +{ + cerr << _("Patience is a virtue.\n"); +} + +void +ARDOUR_UI::session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels) +{ + Route* route; + + if (session == 0) { + warning << _("You cannot add a track without a session already loaded.") << endmsg; + return; + } + + try { + if (disk) { + if ((route = session->new_audio_track (input_channels, output_channels)) == 0) { + error << _("could not create new audio track") << endmsg; + } + } else { + if ((route = session->new_audio_route (input_channels, output_channels)) == 0) { + error << _("could not create new audio bus") << endmsg; + } + } + +#if CONTROLOUTS + if (need_control_room_outs) { + pan_t pans[2]; + + pans[0] = 0.5; + pans[1] = 0.5; + + route->set_stereo_control_outs (control_lr_channels); + route->control_outs()->set_stereo_pan (pans, this); + } +#endif /* CONTROLOUTS */ + } + + catch (...) { + ArdourMessage msg (editor, X_("noport dialog"), + _("There are insufficient JACK ports available\n\ +to create a new track or bus.\n\ +You should save Ardour, exit and\n\ +restart JACK with more ports.")); + } +} + +void +ARDOUR_UI::diskstream_added (DiskStream* ds) +{ + // meter_bridge_dialog_check->set_sensitive (true); +} + +void +ARDOUR_UI::do_transport_locate (jack_nframes_t new_position) +{ + jack_nframes_t _preroll; + + if (session) { + _preroll = session->convert_to_frames_at (new_position, session->preroll); + + if (new_position > _preroll) { + new_position -= _preroll; + } else { + new_position = 0; + } + + session->request_locate (new_position); + } +} + +void +ARDOUR_UI::transport_goto_start () +{ + if (session) { + session->request_locate (0); + + + /* force displayed area in editor to start no matter + what "follow playhead" setting is. + */ + + if (editor) { + editor->reposition_x_origin (0); + } + } +} + +void +ARDOUR_UI::transport_goto_end () +{ + if (session) { + jack_nframes_t frame = session->current_end_frame(); + session->request_locate (frame); + + /* force displayed area in editor to start no matter + what "follow playhead" setting is. + */ + + if (editor) { + editor->reposition_x_origin (frame); + } + } +} + +gint +ARDOUR_UI::mouse_transport_stop (GdkEventButton *ev) +{ + + + if (session) { + if (session->transport_stopped()) { + session->request_locate (session->last_transport_start()); + } else { + if (session->get_auto_loop()) { + session->request_auto_loop (false); + } + + Keyboard::ModifierMask mask = Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift); + session->request_stop (Keyboard::modifier_state_equals (ev->state, mask)); + } + } + + return TRUE; +} + +gint +ARDOUR_UI::mouse_transport_roll (GdkEventButton* ev) +{ + transport_roll (); + return TRUE; +} + +void +ARDOUR_UI::transport_stop () +{ + if (!session) { + return; + } + + if (session->is_auditioning()) { + session->cancel_audition (); + return; + } + + if (session->get_auto_loop()) { + session->request_auto_loop (false); + } + + session->request_stop (); +} + +void +ARDOUR_UI::transport_stop_and_forget_capture () +{ + if (session) { + session->request_stop (true); + } +} + +void +ARDOUR_UI::remove_last_capture() +{ + if (editor) { + editor->remove_last_capture(); + } +} + +void +ARDOUR_UI::transport_record () +{ + if (session) { + switch (session->record_status()) { + case Session::Disabled: + if (session->ntracks() == 0) { + string txt = _("Please create 1 or more track\nbefore trying to record.\nCheck the Session menu."); + ArdourMessage msg (editor, X_("cannotrecenable"), txt); + return; + } + session->maybe_enable_record (); + break; + case Session::Recording: + case Session::Enabled: + session->disable_record (); + } + } +} + +void +ARDOUR_UI::transport_roll () +{ + bool rolling; + + if (!session) { + return; + } + + rolling = session->transport_rolling (); + + if (session->get_auto_loop()) { + session->request_auto_loop (false); + auto_loop_button.set_active (false); + roll_button.set_active (true); + } else if (session->get_play_range ()) { + session->request_play_range (false); + play_selection_button.set_active (false); + } else if (rolling) { + session->request_locate (session->last_transport_start(), true); + } + + session->request_transport_speed (1.0f); +} + +void +ARDOUR_UI::transport_loop() +{ + if (session) { + if (session->get_auto_loop()) { + if (session->transport_rolling()) { + Location * looploc = session->locations()->auto_loop_location(); + if (looploc) { + session->request_locate (looploc->start(), true); + } + } + } + else { + session->request_auto_loop (true); + } + } +} + +void +ARDOUR_UI::transport_play_selection () +{ + if (!session) { + return; + } + + if (!session->get_play_range()) { + session->request_stop (); + } + + editor->play_selection (); +} + +void +ARDOUR_UI::transport_rewind (int option) +{ + float current_transport_speed; + + if (session) { + current_transport_speed = session->transport_speed(); + + if (current_transport_speed >= 0.0f) { + switch (option) { + case 0: + session->request_transport_speed (-1.0f); + break; + case 1: + session->request_transport_speed (-4.0f); + break; + case -1: + session->request_transport_speed (-0.5f); + break; + } + } else { + /* speed up */ + session->request_transport_speed (current_transport_speed * 1.5f); + } + } +} + +void +ARDOUR_UI::transport_forward (int option) +{ + float current_transport_speed; + + if (session) { + current_transport_speed = session->transport_speed(); + + if (current_transport_speed <= 0.0f) { + switch (option) { + case 0: + session->request_transport_speed (1.0f); + break; + case 1: + session->request_transport_speed (4.0f); + break; + case -1: + session->request_transport_speed (0.5f); + break; + } + } else { + /* speed up */ + session->request_transport_speed (current_transport_speed * 1.5f); + } + } +} + +void +ARDOUR_UI::toggle_monitor_enable (guint32 dstream) +{ + if (session == 0) { + return; + } + + DiskStream *ds; + + if ((ds = session->diskstream_by_id (dstream)) != 0) { + Port *port = ds->io()->input (0); + port->request_monitor_input (!port->monitoring_input()); + } +} + +void +ARDOUR_UI::toggle_record_enable (guint32 dstream) +{ + if (session == 0) { + return; + } + + DiskStream *ds; + + if ((ds = session->diskstream_by_id (dstream)) != 0) { + ds->set_record_enabled (!ds->record_enabled(), this); + } +} + +void +ARDOUR_UI::queue_transport_change () +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &ARDOUR_UI::map_transport_state)); +} + +void +ARDOUR_UI::map_transport_state () +{ + float sp = session->transport_speed(); + + if (sp == 1.0f) { + transport_rolling (); + } else if (sp < 0.0f) { + transport_rewinding (); + } else if (sp > 0.0f) { + transport_forwarding (); + } else { + transport_stopped (); + } +} + +void +ARDOUR_UI::send_all_midi_feedback () +{ + if (session) { + session->send_all_midi_feedback(); + } +} + +void +ARDOUR_UI::allow_local_only () +{ + +} + +void +ARDOUR_UI::allow_mmc_only () +{ + +} + +void +ARDOUR_UI::allow_mmc_and_local () +{ + +} + +void +ARDOUR_UI::GlobalClickBox::printer (char buf[32], Adjustment &adj, void *arg) +{ + snprintf (buf, sizeof(buf), "%s", ((GlobalClickBox *) arg)->strings[ + (int) adj.get_value()].c_str()); +} + +void +ARDOUR_UI::engine_stopped () +{ + ENSURE_GUI_THREAD (slot (*this, &ARDOUR_UI::engine_stopped)); + + jack_disconnect_item->set_sensitive (false); + jack_reconnect_item->set_sensitive (true); + jack_bufsize_menu->set_sensitive (false); +} + + +void +ARDOUR_UI::engine_running () +{ + ENSURE_GUI_THREAD (slot (*this, &ARDOUR_UI::engine_running)); + + jack_disconnect_item->set_sensitive (true); + jack_reconnect_item->set_sensitive (false); + jack_bufsize_menu->set_sensitive (true); +} + +void +ARDOUR_UI::engine_halted () +{ + ENSURE_GUI_THREAD (slot (*this, &ARDOUR_UI::engine_halted)); + + jack_disconnect_item->set_sensitive (false); + jack_reconnect_item->set_sensitive (true); + jack_bufsize_menu->set_sensitive (false); + + update_sample_rate (0); + + ArdourMessage msg (editor, X_("halted"), + _("\ +JACK has either been shutdown or it\n\ +disconnected Ardour because Ardour\n\ +was not fast enough. You can save the\n\ +session and/or try to reconnect to JACK .")); +} + +int32_t +ARDOUR_UI::do_engine_start () +{ + try { + engine->start(); + } + + catch (AudioEngine::PortRegistrationFailure& err) { + engine->stop (); + error << _("Unable to create all required ports") + << endmsg; + unload_session (); + return -1; + } + + catch (...) { + engine->stop (); + error << _("Unable to start the session running") + << endmsg; + unload_session (); + return -2; + } + + return 0; +} + +gint +ARDOUR_UI::start_engine () +{ + if (do_engine_start () == 0) { + if (session && _session_is_new) { + /* we need to retain initial visual + settings for a new session + */ + session->save_state (""); + } + + /* there is too much going on, in too many threads, for us to + end up with a clean session. So wait 1 second after loading, + and fix it up. its ugly, but until i come across a better + solution, its what we have. + */ + + Main::timeout.connect (slot (*this, &ARDOUR_UI::make_session_clean), 1000); + } + + return FALSE; +} + +void +ARDOUR_UI::update_clocks () +{ + Clock (session->audible_frame()); /* EMIT_SIGNAL */ +} + +void +ARDOUR_UI::start_clocking () +{ + clock_signal_connection = RapidScreenUpdate.connect (slot (*this, &ARDOUR_UI::update_clocks)); +} + +void +ARDOUR_UI::stop_clocking () +{ + clock_signal_connection.disconnect (); +} + +void +ARDOUR_UI::toggle_clocking () +{ +#if 0 + if (clock_button.get_active()) { + start_clocking (); + } else { + stop_clocking (); + } +#endif +} + +gint +ARDOUR_UI::_blink (void *arg) + +{ + ((ARDOUR_UI *) arg)->blink (); + return TRUE; +} + +void +ARDOUR_UI::blink () +{ + Blink (blink_on = !blink_on); /* EMIT_SIGNAL */ +} + +void +ARDOUR_UI::start_blinking () +{ + /* Start the blink signal. Everybody with a blinking widget + uses Blink to drive the widget's state. + */ + + if (blink_timeout_tag < 0) { + blink_on = false; + blink_timeout_tag = gtk_timeout_add (240, _blink, this); + } +} + +void +ARDOUR_UI::stop_blinking () +{ + if (blink_timeout_tag >= 0) { + gtk_timeout_remove (blink_timeout_tag); + blink_timeout_tag = -1; + } +} + + +void +ARDOUR_UI::add_diskstream_to_menu (DiskStream& dstream) +{ + using namespace Gtk; + using namespace Menu_Helpers; + + if (dstream.hidden()) { + return; + } + + MenuList& items = diskstream_menu->items(); + items.push_back (MenuElem (dstream.name(), bind (slot (*this, &ARDOUR_UI::diskstream_selected), (gint32) dstream.id()))); +} + +void +ARDOUR_UI::diskstream_selected (gint32 id) +{ + selected_dstream = id; + Main::quit (); +} + +gint32 +ARDOUR_UI::select_diskstream (GdkEventButton *ev) +{ + using namespace Gtk; + using namespace Menu_Helpers; + + if (session == 0) { + return -1; + } + + diskstream_menu = new Menu(); + diskstream_menu->set_name ("ArdourContextMenu"); + using namespace Gtk; + using namespace Menu_Helpers; + + MenuList& items = diskstream_menu->items(); + items.push_back (MenuElem (_("No Stream"), (bind (slot (*this, &ARDOUR_UI::diskstream_selected), -1)))); + + session->foreach_diskstream (this, &ARDOUR_UI::add_diskstream_to_menu); + + if (ev) { + diskstream_menu->popup (ev->button, ev->time); + } else { + diskstream_menu->popup (0, 0); + } + + selected_dstream = -1; + + Main::run (); + + delete diskstream_menu; + + return selected_dstream; +} + +void +ARDOUR_UI::name_io_setup (AudioEngine& engine, + string& buf, + IO& io, + bool in) +{ + if (in) { + if (io.n_inputs() == 0) { + buf = _("none"); + return; + } + + /* XXX we're not handling multiple ports yet. */ + + const char **connections = io.input(0)->get_connections(); + + if (connections == 0 || connections[0] == '\0') { + buf = _("off"); + } else { + buf = connections[0]; + } + + free (connections); + + } else { + + if (io.n_outputs() == 0) { + buf = _("none"); + return; + } + + /* XXX we're not handling multiple ports yet. */ + + const char **connections = io.output(0)->get_connections(); + + if (connections == 0 || connections[0] == '\0') { + buf = _("off"); + } else { + buf = connections[0]; + } + + free (connections); + } +} + +void +ARDOUR_UI::snapshot_session () +{ + ArdourPrompter prompter (true); + string now; + time_t n; + + time (&n); + now = ctime (&n); + now = now.substr (0, now.length() - 1); + + prompter.set_name ("Prompter"); + prompter.set_prompt (_("Name for snapshot")); + prompter.set_initial_text (now); + prompter.done.connect (Gtk::Main::quit.slot()); + prompter.show_all (); + + Gtk::Main::run (); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string snapname; + + prompter.get_result (snapname); + if (snapname.length()){ + save_state (snapname); + } + } +} + +void +ARDOUR_UI::save_state (string name) +{ + (void) save_state_canfail (name); +} + +int +ARDOUR_UI::save_state_canfail (string name) +{ + if (session) { + int ret; + + if (name.length() == 0) { + name = session->snap_name(); + } + + if ((ret = session->save_state (name)) != 0) { + return ret; + } + } + save_ardour_state (); /* XXX cannot fail? yeah, right ... */ + return 0; +} + +void +ARDOUR_UI::restore_state (string name) +{ + if (session) { + if (name.length() == 0) { + name = session->name(); + } + session->restore_state (name); + } +} + +void +ARDOUR_UI::allow_focus (bool yn) +{ + if (keyboard) { + keyboard->allow_focus (yn); + } +} + +void +ARDOUR_UI::primary_clock_value_changed () +{ + if (session) { + session->request_locate (primary_clock.current_time ()); + } +} + +void +ARDOUR_UI::secondary_clock_value_changed () +{ + if (session) { + session->request_locate (secondary_clock.current_time ()); + } +} + +void +ARDOUR_UI::rec_enable_button_blink (bool onoff, DiskStream *dstream, Widget *w) +{ + if (session && dstream && dstream->record_enabled()) { + + Session::RecordState rs; + + rs = session->record_status (); + + switch (rs) { + case Session::Disabled: + case Session::Enabled: + if (w->get_state() != GTK_STATE_SELECTED) { + w->set_state (GTK_STATE_SELECTED); + } + break; + + case Session::Recording: + if (w->get_state() != GTK_STATE_ACTIVE) { + w->set_state (GTK_STATE_ACTIVE); + } + break; + } + + } else { + if (w->get_state() != GTK_STATE_NORMAL) { + w->set_state (GTK_STATE_NORMAL); + } + } +} + +void +ARDOUR_UI::transport_rec_enable_blink (bool onoff) +{ + if (session == 0) { + return; + } + + switch (session->record_status()) { + case Session::Enabled: + if (onoff) { + rec_button.set_state (GTK_STATE_ACTIVE); + } else { + rec_button.set_state (GTK_STATE_NORMAL); + } + break; + + case Session::Recording: + rec_button.set_state (GTK_STATE_ACTIVE); + break; + + default: + rec_button.set_active (false); + rec_button.set_state (GTK_STATE_NORMAL); + break; + } +} + +gint +ARDOUR_UI::generic_focus_in_event (GdkEventFocus *ev) +{ + ARDOUR_UI::instance()->allow_focus (true); + return FALSE; +} + +gint +ARDOUR_UI::generic_focus_out_event (GdkEventFocus *ev) +{ + ARDOUR_UI::instance()->allow_focus (false); + return FALSE; +} + +gint +ARDOUR_UI::hide_and_quit (GdkEventAny *ev, ArdourDialog *window) +{ + window->hide(); + Gtk::Main::quit (); + return TRUE; +} + +void +ARDOUR_UI::start_keyboard_prefix () +{ + keyboard->start_prefix(); +} + +void +ARDOUR_UI::save_template () + +{ + ArdourPrompter prompter (true); + prompter.set_name ("Prompter"); + prompter.set_prompt (_("Name for mix template:")); + prompter.set_initial_text(session->name() + _("-template")); + + prompter.done.connect(Gtk::Main::quit.slot()); + prompter.show_all(); + + Gtk::Main::run(); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string name; + + prompter.get_result (name); + + if (name.length()) { + session->save_template (name); + } + } +} + +void +ARDOUR_UI::new_session (bool startup, string predetermined_path) +{ + if (new_session_window == 0){ + new_session_window = new NewSessionDialog (*engine, startup, predetermined_path); + editor->ensure_float (*new_session_window); + } + + new_session_window->run (); + + /* write favorites either way */ + Session::FavoriteDirs favs; + new_session_window->file_selector.get_favorites (favs); + Session::write_favorite_dirs (favs); + + if (new_session_window->run_status()) { + return; + } + + string session_path = new_session_window->file_selector.get_path (); + string session_name = PBD::basename (session_path); + + // Check that it doesn't already exist. + access(session_path.c_str(), R_OK); + if (errno != ENOENT){ + error << compose(_("Session %1 already exists at %2"), session_name, session_path) << endmsg; + return; + } + + _session_is_new = true; + + if (session_path[session_path.length()-1] != '/') { + + string template_name = new_session_window->get_template_name (); + + if (template_name.length()) { + + load_session (session_path, session_name, &template_name); + + } else { + + uint32_t cchns; + uint32_t mchns; + Session::AutoConnectOption iconnect; + Session::AutoConnectOption oconnect; + + if (new_session_window->use_control_button.get_active()) { + cchns = (uint32_t) channel_combo_get_channel_count (new_session_window->control_out_channel_combo); + } else { + cchns = 0; + } + if (new_session_window->use_master_button.get_active()) { + mchns = (uint32_t) channel_combo_get_channel_count (new_session_window->master_out_channel_combo); + } else { + mchns = 0; + } + + if (new_session_window->connect_to_physical_inputs_button.get_active()) { + iconnect = Session::AutoConnectPhysical; + } else { + iconnect = Session::AutoConnectOption (0); + } + + if (new_session_window->connect_to_master_button.get_active ()) { + oconnect = Session::AutoConnectMaster; + } else if (new_session_window->connect_to_physical_outputs_button.get_active ()) { + oconnect = Session::AutoConnectPhysical; + } else { + oconnect = Session::AutoConnectOption (0); + } + + uint32_t nphysin = (uint32_t) new_session_window->in_count_adjustment.get_value(); + uint32_t nphysout = (uint32_t) new_session_window->out_count_adjustment.get_value(); + + build_session (session_path, session_name, cchns, mchns, iconnect, oconnect, nphysin, nphysout, + engine->frame_rate() * 60 * 5); + } + } +} + +int +ARDOUR_UI::load_session (string path, string snap_name, string* mix_template) +{ + Session *new_session; + int x; + session_loaded = false; + x = unload_session (); + + if (x < 0) { + return -1; + } else if (x > 0) { + return 0; + } + + /* if it already exists, we must have write access */ + + if (::access (path.c_str(), F_OK) == 0 && ::access (path.c_str(), W_OK)) { + ArdourMessage msg (editor, X_("noaccess dialog"), _("\ +You do not have write access to this session.\n\ +This prevents the session from being loaded.")); + return -1; + } + + try { + new_session = new Session (*engine, path, snap_name, mix_template); + } + + catch (...) { + + error << compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg; + return -1; + } + + connect_to_session (new_session); + + //if (engine->running()) { + //mixer->show_window(); + //} + session_loaded = true; + return 0; +} + +int +ARDOUR_UI::make_session_clean () +{ + if (session) { + session->set_clean (); + } + + return FALSE; +} + +int +ARDOUR_UI::build_session (string path, string snap_name, + uint32_t control_channels, + uint32_t master_channels, + Session::AutoConnectOption input_connect, + Session::AutoConnectOption output_connect, + uint32_t nphysin, + uint32_t nphysout, + jack_nframes_t initial_length) +{ + Session *new_session; + int x; + + session_loaded = false; + x = unload_session (); + if (x < 0) { + return -1; + } else if (x > 0) { + return 0; + } + + _session_is_new = true; + + try { + new_session = new Session (*engine, path, snap_name, input_connect, output_connect, + control_channels, master_channels, nphysin, nphysout, initial_length); + } + + catch (...) { + + error << compose(_("Session \"%1 (snapshot %2)\" did not load successfully"), path, snap_name) << endmsg; + return -1; + } + + connect_to_session (new_session); + + //if (engine->running()) { + //mixer->show_window(); + //} + session_loaded = true; + return 0; +} + +void +ARDOUR_UI::hide_dialog (ArdourDialog *dialog) +{ + dialog->hide_all(); +} + +void +ARDOUR_UI::show () +{ + if (editor) { + editor->show_window (); + shown_flag = true; + } + + if (session && mixer) { + mixer->show_window (); + } + + if (about) { + about->get_window().raise (); + } +} + +void +ARDOUR_UI::show_splash () +{ + if (about == 0) { + about = new About(this); + about->show_all(); + about->show_sub (true); + about->get_window().raise (); + } + else { + about->get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + about->show_all (); + about->get_window().raise (); + } +} + +void +ARDOUR_UI::hide_splash () +{ + if (about) { + // about->hide(); + } +} + +void +ARDOUR_UI::display_cleanup_results (Session::cleanup_report& rep, const gchar* list_title, string msg) +{ + size_t removed; + + removed = rep.paths.size(); + + if (removed == 0) { + ArdourMessage msg (editor, X_("cleanupresults"), + _("\ +No audio files were ready for cleanup\n\n\ +If this seems suprising, check for any existing\n\ +snapshots. These may still include regions that\n\ +require some unused files to continue to exist.")); + return; + } + + ArdourDialog results ("cleanup results"); + + const gchar* list_titles[] = { + list_title, + 0 + }; + + Gtk::CList list (internationalize (list_titles)); + Gtk::ScrolledWindow list_scroller; + Gtk::Label txt; + Gtk::Button ok_button (_("OK")); + Gtk::VBox vpacker; + const char* rowtext[1]; + + list_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + vpacker.set_border_width (10); + vpacker.set_spacing (10); + + if (rep.space < 1048576.0f) { + if (removed > 1) { + txt.set_text (compose (msg, removed, _("files"), (float) rep.space / 1024.0f, "kilo")); + } else { + txt.set_text (compose (msg, removed, _("file"), (float) rep.space / 1024.0f, "kilo")); + } + } else { + if (removed > 1) { + txt.set_text (compose (msg, removed, _("files"), (float) rep.space / 1048576.0f, "mega")); + } else { + txt.set_text (compose (msg, removed, _("file"), (float) rep.space / 1048576.0f, "mega")); + } + } + + vpacker.pack_start (txt, false, false); + + for (vector::iterator i = rep.paths.begin(); i != rep.paths.end(); ++i) { + rowtext[0] = (*i).c_str(); + list.rows().push_back (rowtext); + } + + list_scroller.add_with_viewport (list); + list_scroller.set_usize (-1, 250); + + vpacker.pack_start (list_scroller, true, true); + vpacker.pack_start (ok_button, false, false); + + ok_button.clicked.connect (Main::quit.slot ()); + results.Hiding.connect (Main::quit.slot ()); + + results.add (vpacker); + + results.set_position (GTK_WIN_POS_MOUSE); + results.set_title (_("ardour: cleanup")); + results.set_modal (true); + results.run (); +} + +void +ARDOUR_UI::cleanup () +{ + if (session == 0) { + /* shouldn't happen: menu item is insensitive */ + return; + } + + ArdourDialog checker (X_("cleanup confirm dialog")); + Gtk::Label label (_("\ +Cleanup is a destructive operation.\n\ +ALL undo/redo information will be lost if you cleanup.\n\ +Unused audio files will be moved to a \"dead sounds\" location.")); + + Gtk::Button ok_button (_("Proceed with cleanup")); + Gtk::Button cancel_button (_("Cancel")); + Gtk::HBox bbox; + Gtk::VBox vbox; + + bbox.set_border_width (6); + bbox.set_spacing (12); + bbox.pack_start (ok_button, true, false); + bbox.pack_start (cancel_button, true, false); + + vbox.set_border_width (6); + vbox.set_spacing (12); + vbox.pack_start (label, false, false); + vbox.pack_start (bbox, false, false); + + checker.add (vbox); + checker.set_name (_("CleanupDialog")); + checker.set_title (_("ardour cleanup")); + checker.set_wmclass (_("ardour_cleanup"), "Ardour"); + checker.set_position (GTK_WIN_POS_MOUSE); + checker.realize (); + checker.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + + ok_button.clicked.connect (bind (slot (checker, &ArdourDialog::stop), 1)); + cancel_button.clicked.connect (bind (slot (checker, &ArdourDialog::stop), 0)); + + checker.run (); + + if (checker.run_status() != 1) { + return; + } + + Session::cleanup_report rep; + + editor->prepare_for_cleanup (); + + if (session->cleanup_sources (rep)) { + return; + } + + display_cleanup_results (rep, + _("cleaned files"), + _("\ +The following %1 %2 were not in use.\n\ +The next time you flush the wastebasket\n\ +it will release an additional %3 %4bytes\n\ +of disk space" + )); +} + +void +ARDOUR_UI::flush_trash () +{ + if (session == 0) { + /* shouldn't happen: menu item is insensitive */ + return; + } + + Session::cleanup_report rep; + + if (session->cleanup_trash_sources (rep)) { + return; + } + + display_cleanup_results (rep, + _("deleted file"), + _("The following %1 file%2 were deleted, releasing %3 %4bytes of disk space")); +} + +void +ARDOUR_UI::add_route () +{ + int count; + + if (!session) { + return; + } + + if (add_route_dialog == 0) { + add_route_dialog = new AddRouteDialog; + editor->ensure_float (*add_route_dialog); + } + + if (add_route_dialog->is_visible()) { + /* we're already doing this */ + return; + } + + add_route_dialog->run (); + + if (add_route_dialog->run_status()) { + return; + } + + if ((count = add_route_dialog->count()) <= 0) { + return; + } + + uint32_t input_chan = add_route_dialog->channels (); + uint32_t output_chan; + string name_template = add_route_dialog->name_template (); + bool track = add_route_dialog->track (); + + Session::AutoConnectOption oac = session->get_output_auto_connect(); + + if (oac & Session::AutoConnectMaster) { + output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan); + } else { + output_chan = input_chan; + } + + /* XXX do something with name template */ + + while (count) { + if (track) { + session_add_audio_track (input_chan, output_chan); + } else { + session_add_audio_bus (input_chan, output_chan); + } + --count; + + while (Main::events_pending()) { + Main::iteration (); + } + } +} + +XMLNode* +ARDOUR_UI::mixer_settings () const +{ + XMLNode* node = 0; + + if (session) { + node = session->instant_xml(X_("Mixer"), session->path()); + } else { + node = Config->instant_xml(X_("Mixer"), Config->get_user_ardour_path()); + } + + if (!node) { + node = new XMLNode (X_("Mixer")); + } + + return node; +} + +XMLNode* +ARDOUR_UI::editor_settings () const +{ + XMLNode* node = 0; + + if (session) { + node = session->instant_xml(X_("Editor"), session->path()); + } else { + node = Config->instant_xml(X_("Editor"), Config->get_user_ardour_path()); + } + + if (!node) { + node = new XMLNode (X_("Editor")); + } + return node; +} + +XMLNode* +ARDOUR_UI::keyboard_settings () const +{ + XMLNode* node = 0; + + node = Config->extra_xml(X_("Keyboard")); + + if (!node) { + node = new XMLNode (X_("Keyboard")); + } + return node; +} + +void +ARDOUR_UI::halt_on_xrun_message () +{ + ENSURE_GUI_THREAD (slot (*this, &ARDOUR_UI::halt_on_xrun_message)); + + ArdourMessage msg (editor, X_("haltonxrun"), + _("Recording was stopped because your system could not keep up.")); +} + +void +ARDOUR_UI::delete_sources_in_the_right_thread (list* deletion_list) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &ARDOUR_UI::delete_sources_in_the_right_thread), deletion_list)); + + for (list::iterator i = deletion_list->begin(); i != deletion_list->end(); ++i) { + delete *i; + } + + delete deletion_list; +} + +void +ARDOUR_UI::disk_overrun_handler () +{ + ENSURE_GUI_THREAD (slot (*this, &ARDOUR_UI::disk_underrun_handler)); + + if (!have_disk_overrun_displayed) { + have_disk_overrun_displayed = true; + ArdourMessage msg (editor, X_("diskrate dialog"), _("\ +The disk system on your computer\n\ +was not able to keep up with Ardour.\n\ +\n\ +Specifically, it failed to write data to disk\n\ +quickly enough to keep up with recording.\n")); + have_disk_overrun_displayed = false; + } +} + +void +ARDOUR_UI::disk_underrun_handler () +{ + ENSURE_GUI_THREAD (slot (*this, &ARDOUR_UI::disk_underrun_handler)); + + if (!have_disk_underrun_displayed) { + have_disk_underrun_displayed = true; + ArdourMessage msg (editor, X_("diskrate2 dialog"), + (_("The disk system on your computer\n\ +was not able to keep up with Ardour.\n\ +\n\ +Specifically, it failed to read data from disk\n\ +quickly enough to keep up with playback.\n"))); + have_disk_underrun_displayed = false; + } +} + +void +ARDOUR_UI::disk_underrun_message_gone () +{ + have_disk_underrun_displayed = false; +} + +void +ARDOUR_UI::disk_overrun_message_gone () +{ + have_disk_underrun_displayed = false; +} + +int +ARDOUR_UI::pending_state_dialog () +{ + ArdourDialog dialog ("pending state dialog"); + Button use_button (_("Recover from crash")); + Button cancel_button (_("Ignore crash data")); + Label message (_("\ +This session appears to have been in\n\ +middle of recording when ardour or\n\ +the computer was shutdown.\n\ +\n\ +Ardour can recover any captured audio for\n\ +you, or it can ignore it. Please decide\n\ +what you would like to do.\n")); + HBox hpacker; + VBox vpacker; + + vpacker.set_border_width (12); + vpacker.set_spacing (7); + vpacker.pack_start (message); + vpacker.pack_start (hpacker); + + hpacker.set_spacing (7); + hpacker.pack_start (use_button); + hpacker.pack_start (cancel_button); + + use_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 0)); + cancel_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 1)); + + dialog.add (vpacker); + dialog.set_position (GTK_WIN_POS_CENTER); + dialog.show_all (); + dialog.realize(); + dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + + dialog.run (); + + if (dialog.run_status () == 0) { + return 1; + } + + return 0; +} + + +void +ARDOUR_UI::disconnect_from_jack () +{ + if (engine) { + if( engine->disconnect_from_jack ()) { + ArdourMessage msg (editor, X_("nojack dialog"), + _("Could not disconnect from JACK")); + } + + update_sample_rate (0); + } +} + +void +ARDOUR_UI::reconnect_to_jack () +{ + if (engine) { + if (engine->reconnect_to_jack ()) { + ArdourMessage msg (editor, X_("nojack dialog"), + _("Could not reconnect to JACK")); + } + + update_sample_rate (0); + } +} + +void +ARDOUR_UI::set_jack_buffer_size (jack_nframes_t nframes) +{ + engine->request_buffer_size (nframes); + update_sample_rate (0); +} + +int +ARDOUR_UI::cmdline_new_session (string path) +{ + if (path[0] != '/') { + char buf[PATH_MAX+1]; + string str; + + getcwd (buf, sizeof (buf)); + str = buf; + str += '/'; + str += path; + path = str; + } + + new_session (false, path); + + _will_create_new_session_automatically = false; /* done it */ + return FALSE; /* don't call it again */ +} diff --git a/gtk2_ardour/ardour_ui.h b/gtk2_ardour/ardour_ui.h new file mode 100644 index 0000000000..34f3422e50 --- /dev/null +++ b/gtk2_ardour/ardour_ui.h @@ -0,0 +1,728 @@ +/* + Copyright (C) 1999-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gui_h__ +#define __ardour_gui_h__ + +/* need _BSD_SOURCE to get timersub macros */ + +#ifdef _BSD_SOURCE +#include +#else +#define _BSD_SOURCE +#include +#undef _BSD_SOURCE +#endif + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "audio_clock.h" +#include "ardour_dialog.h" +#include "editing.h" + +class AudioClock; +class PublicEditor; +class Keyboard; +class MeterBridge; +class OptionEditor; +class Mixer_UI; +class ConnectionEditor; +class RouteParams_UI; +class SoundFileSelector; +class About; +class AddRouteDialog; +class NewSessionDialog; +class LocationUI; + +namespace Gtkmmext { + class TearOff; +}; + +namespace ARDOUR { + class AudioEngine; + class Route; + class Port; + class IO; +}; + +namespace ALSA { + class MultiChannelDevice; +}; + +#define FRAME_NAME "BaseFrame" + +class ARDOUR_UI : public Gtkmmext::UI +{ + public: + ARDOUR_UI (int *argcp, char **argvp[], string rcfile); + ~ARDOUR_UI(); + + void show (); + bool shown() { return shown_flag; } + + void show_splash (); + void hide_splash (); + + int load_session (string path, string snapshot, string* mix_template = 0); + bool session_loaded; + int build_session (string path, string snapshot, + uint32_t ctl_chns, + uint32_t master_chns, + ARDOUR::Session::AutoConnectOption input_connect, + ARDOUR::Session::AutoConnectOption output_connect, + uint32_t nphysin, + uint32_t nphysout, + jack_nframes_t initial_length); + bool session_is_new() const { return _session_is_new; } + + ARDOUR::Session* the_session() { return session; } + + bool will_create_new_session_automatically() const { + return _will_create_new_session_automatically; + } + + void set_will_create_new_session_automatically (bool yn) { + _will_create_new_session_automatically = yn; + } + + void new_session (bool startup = false, std::string path = string()); + gint cmdline_new_session (std::string path); + int unload_session (); + void close_session() { unload_session(); } + + int save_state_canfail (string state_name = ""); + void save_state (string state_name = ""); + void restore_state (string state_name = ""); + + static double gain_to_slider_position (ARDOUR::gain_t g); + static ARDOUR::gain_t slider_position_to_gain (double pos); + + static ARDOUR_UI *instance () { return theArdourUI; } + + PublicEditor& the_editor(){return *editor;} + Mixer_UI* the_mixer() { return mixer; } + + void allow_focus (bool yn); + + static gint generic_focus_in_event (GdkEventFocus *); + static gint generic_focus_out_event (GdkEventFocus *); + + void toggle_location_window (); + void toggle_big_clock_window (); + void toggle_connection_editor (); + void toggle_route_params_window (); + void toggle_tempo_window (); + void toggle_sfdb_window (); + + SoundFileSelector& get_sfdb_window(); + + gint32 select_diskstream (GdkEventButton *ev); + + Gtk::Tooltips& tooltips() { return _tooltips; } + + static SigC::Signal1 Blink; + static SigC::Signal0 RapidScreenUpdate; + static SigC::Signal0 SuperRapidScreenUpdate; + static SigC::Signal1 Clock; + + /* this is a helper function to centralize the (complex) logic for + blinking rec-enable buttons. + */ + + void rec_enable_button_blink (bool onoff, ARDOUR::DiskStream *, Gtk::Widget *w); + + void name_io_setup (ARDOUR::AudioEngine&, string&, ARDOUR::IO& io, bool in); + void choose_io (ARDOUR::IO&, bool input); + + static gint hide_and_quit (GdkEventAny *ev, ArdourDialog *); + + XMLNode* editor_settings() const; + XMLNode* mixer_settings () const; + XMLNode* keyboard_settings () const; + + void save_ardour_state (); + gboolean configure_handler (GdkEventConfigure* conf); + + void do_transport_locate (jack_nframes_t position); + void halt_on_xrun_message (); + + AudioClock primary_clock; + AudioClock secondary_clock; + AudioClock preroll_clock; + AudioClock postroll_clock; + + void add_route (); + + void session_add_audio_track (int input_channels, int32_t output_channels) { + session_add_audio_route (true, input_channels, output_channels); + } + + void session_add_audio_bus (int input_channels, int32_t output_channels) { + session_add_audio_route (false, input_channels, output_channels); + } + + void session_add_midi_track (); + + void set_engine (ARDOUR::AudioEngine&); + + gint exit_on_main_window_close (GdkEventAny *); + + protected: + friend class PublicEditor; + + void toggle_metering (); + void toggle_clocking (); + void toggle_auto_play (); + void toggle_auto_input (); + void toggle_punch_in (); + void toggle_punch_out (); + void toggle_auto_return (); + void toggle_click (); + void toggle_follow (); + + void toggle_session_auto_loop (); + void toggle_session_punch_in (); + + void toggle_options_window (); + + private: + struct GlobalClickBox : public Gtk::VBox { + Gtkmmext::ClickBox *box; + Gtk::Frame frame; + Gtk::Label label; + vector &strings; + Gtk::Adjustment adjustment; + + static void printer (char buf[32], Gtk::Adjustment &adj, void *arg); + + GlobalClickBox (const string &str, vector &vs) + : strings (vs), + adjustment (0, 0, vs.size() - 1, 1, 1, 0) { + box = new Gtkmmext::ClickBox (&adjustment, "ClickButton"); + label.set_text (str); + label.set_name ("GlobalButtonLabel"); + frame.add (*box); + frame.set_shadow_type (GTK_SHADOW_IN); + pack_start (label); + pack_start (frame); + box->set_print_func (printer, this); + box->set_wrap (true); + }; + }; + + ARDOUR::AudioEngine *engine; + ARDOUR::Session *session; + + Gtk::Tooltips _tooltips; + + void goto_editor_window (); + void goto_mixer_window (); + + Gtk::Table adjuster_table; + Gtk::Frame adjuster_frame; + Gtk::Fixed adjuster_base; + + GlobalClickBox *online_control_button; + vector online_control_strings; + + GlobalClickBox *crossfade_time_button; + vector crossfade_time_strings; + + GlobalClickBox *mmc_id_button; + vector mmc_id_strings; + + Gtk::ToggleButton preroll_button; + Gtk::ToggleButton postroll_button; + + Gtk::Table transport_table; + Gtk::Table option_table; + + static SoundFileSelector* sfdb_window; + + int setup_windows (); + void setup_session_menu (); + void setup_transport (); + void setup_clock (); + void setup_session_info (); + void setup_adjustables (); + + Gtk::MenuBar* make_menubar (); + + static ARDOUR_UI *theArdourUI; + + void startup (); + void shutdown (); + + void finish(); + int ask_about_saving_session (string why); + gint ask_about_save_deleted (GdkEventAny*); + void save_session_choice_made (int); + int save_the_session; + + void queue_transport_change (); + void map_transport_state (); + int32_t do_engine_start (); + gint start_engine (); + + void engine_halted (); + void engine_stopped (); + void engine_running (); + + void map_some_session_state (Gtk::ToggleButton& button, + bool (ARDOUR::Session::*get)() const); + + void toggle_some_session_state (Gtk::ToggleButton& button, + bool (ARDOUR::Session::*get)() const, + void (ARDOUR::Session::*set)(bool)); + void map_button_state (); + + void clear_meters (); + + static gint _blink (void *); + void blink (); + gint blink_timeout_tag; + bool blink_on; + void start_blinking (); + void stop_blinking (); + + void control_methods_adjusted (); + void mmc_device_id_adjusted (); + + private: + Gtk::VBox top_packer; + + SigC::Connection clock_signal_connection; + void update_clocks (); + void start_clocking (); + void stop_clocking (); + + class BigClockWindow : public ArdourDialog + { + public: + BigClockWindow () : ArdourDialog ("big clock window") {}; + }; + + AudioClock big_clock; + Gtk::Frame big_clock_frame; + BigClockWindow* big_clock_window; + + void big_clock_size_event (GtkAllocation *alloc); + void big_clock_realize (); + + /* Transport Control */ + + void detach_tearoff (Gtk::Box* parent, Gtk::Widget* contents); + void reattach_tearoff (Gtk::Box* parent, Gtk::Widget* contents, int32_t order); + + Gtkmmext::TearOff* transport_tearoff; + Gtk::Frame transport_frame; + Gtk::HBox transport_tearoff_hbox; + Gtk::HBox transport_hbox; + Gtk::Fixed transport_base; + Gtk::Fixed transport_button_base; + Gtk::Frame transport_button_frame; + Gtk::HBox transport_button_hbox; + Gtk::VBox transport_button_vbox; + Gtk::HBox transport_option_button_hbox; + Gtk::VBox transport_option_button_vbox; + Gtk::HBox transport_clock_hbox; + Gtk::VBox transport_clock_vbox; + Gtk::HBox primary_clock_hbox; + Gtk::HBox secondary_clock_hbox; + + Gtk::Button goto_start_button; + Gtk::Button goto_end_button; + Gtk::Button rewind_button; + Gtk::Button forward_button; + Gtk::Button stop_button; + + enum ShuttleBehaviour { + Sprung, + Wheel + }; + + enum ShuttleUnits { + Percentage, + Semitones + }; + + Gtk::DrawingArea shuttle_box; + Gtk::EventBox speed_display_box; + Gtk::Label speed_display_label; + Gtk::Button shuttle_units_button; + Gtk::Button shuttle_style_button; + Gtk::Menu shuttle_unit_menu; + Gtk::Menu shuttle_style_menu; + ShuttleBehaviour shuttle_behaviour; + ShuttleUnits shuttle_units; + + void shuttle_style_clicked (); + void shuttle_unit_clicked (); + void set_shuttle_behaviour (ShuttleBehaviour); + void set_shuttle_units (ShuttleUnits); + void update_speed_display (); + + gint shuttle_box_button_press (GdkEventButton*); + gint shuttle_box_button_release (GdkEventButton*); + gint shuttle_box_motion (GdkEventMotion*); + gint shuttle_box_expose (GdkEventExpose*); + gint mouse_shuttle (double x, bool force); + void use_shuttle_fract (bool force); + + bool shuttle_grabbed; + double shuttle_fract; + + Gtk::ToggleButton auto_loop_button; + Gtk::ToggleButton play_selection_button; + Gtk::ToggleButton roll_button; + + Gtk::ToggleButton rec_button; + Gtk::ToggleButton punch_in_button; + Gtk::ToggleButton punch_out_button; + Gtk::ToggleButton auto_return_button; + Gtk::ToggleButton auto_play_button; + Gtk::ToggleButton auto_input_button; + Gtk::ToggleButton click_button; + Gtk::ToggleButton follow_button; + Gtk::ToggleButton auditioning_alert_button; + Gtk::ToggleButton solo_alert_button; + + Gtk::VBox alert_box; + + void follow_changed (); + + void solo_blink (bool); + void audition_blink (bool); + + void soloing_changed (bool); + void auditioning_changed (bool); + void _auditioning_changed (bool); + + void solo_alert_toggle (); + void audition_alert_toggle (); + + void primary_clock_value_changed (); + void secondary_clock_value_changed (); + + /* called by Blink signal */ + + void transport_rec_enable_blink (bool onoff); + + /* These change where we accept control from: + MMC, X (local) or both. + */ + + void allow_mmc_only (); + void allow_mmc_and_local (); + void allow_local_only (); + + static void rate_printer (char buf[32], Gtk::Adjustment &, void *); + + Gtk::Menu* session_popup_menu; + Gtk::CTree session_selector; + ArdourDialog* session_selector_window; + + Gtk::FileSelection* open_session_selector; + + void build_session_selector(); + void session_selection (Gtk::CTree::Row, gint col); + struct RecentSessionsSorter { + bool operator() (std::pair a, std::pair b) const { + return cmp_nocase(a.first, b.first) == -1; + } + }; + void redisplay_recent_sessions(); + + /* menu bar and associated stuff */ + + Gtk::MenuBar menu_bar; + Gtk::Fixed menu_bar_base; + Gtk::HBox menu_hbox; + + void build_menu_bar (); + void pack_toplevel_controls(); + + /* handles on the menu bar items that need to + be sensitive to whether or not we have + a session loaded. + */ + + Gtk::MenuItem *add_track_item; + Gtk::MenuItem *save_item; + Gtk::MenuItem *snapshot_item; + Gtk::MenuItem *save_as_item; + Gtk::MenuItem *save_template_item; + Gtk::MenuItem *export_item; + Gtk::MenuItem *close_item; + + Gtk::CheckMenuItem *meter_bridge_dialog_check; + Gtk::CheckMenuItem *connection_editor_check; + Gtk::CheckMenuItem *route_params_check; + Gtk::CheckMenuItem *locations_dialog_check; + Gtk::CheckMenuItem *big_clock_check; + Gtk::CheckMenuItem *tempo_editor_check; + Gtk::CheckMenuItem *sfdb_check; + Gtk::CheckMenuItem *options_window_check; + + /* */ + Gtk::MenuItem *image_compositor_item ; + /* */ + + + Gtk::Label wall_clock_label; + Gtk::EventBox wall_clock_box; + gint update_wall_clock (); + + Gtk::Label disk_space_label; + Gtk::EventBox disk_space_box; + void update_disk_space (); + + Gtk::Label cpu_load_label; + Gtk::EventBox cpu_load_box; + void update_cpu_load (); + + Gtk::Label disk_rate_label; + Gtk::EventBox disk_rate_box; + void update_disk_rate(); + + Gtk::Label buffer_load_label; + Gtk::EventBox buffer_load_box; + void update_buffer_load (); + + Gtk::Label sample_rate_label; + Gtk::EventBox sample_rate_box; + void update_sample_rate (jack_nframes_t); + + gint every_second (); + gint every_point_one_seconds (); + gint every_point_zero_one_seconds (); + + SigC::Connection second_connection; + SigC::Connection point_one_second_connection; + SigC::Connection point_zero_one_second_connection; + + void diskstream_added (ARDOUR::DiskStream*); + + gint session_menu (GdkEventButton *); + + bool _will_create_new_session_automatically; + + NewSessionDialog* new_session_window; + string template_name; + + void new_session_ok_clicked (); + void new_session_template_choice (Gtkmmext::Selector *, Gtkmmext::SelectionResult*); + void hide_dialog (ArdourDialog *dialog); + + void fs_cancel_clicked (Gtk::FileSelection*); + gint fs_delete_event (GdkEventAny*, Gtk::FileSelection*); + + void open_session (); + void open_recent_session (); + void open_ok_clicked (); + + void save_template (); + + + void session_add_audio_route (bool disk, int32_t input_channels, int32_t output_channels); + + void add_diskstream_to_menu (ARDOUR::DiskStream&); + void diskstream_selected (gint32); + Gtk::Menu *diskstream_menu; + gint32 selected_dstream; + + gint mouse_transport_goto_start (GdkEventButton *) { + transport_goto_start (); return TRUE; + } + gint mouse_transport_goto_end (GdkEventButton *) { + transport_goto_end (); return TRUE; + } + gint mouse_transport_record (GdkEventButton *) { + transport_record (); return TRUE; + } + gint mouse_transport_forward (GdkEventButton *) { + transport_forward (0); return TRUE; + } + gint mouse_transport_rewind (GdkEventButton *) { + transport_rewind (0); return TRUE; + } + gint mouse_transport_loop (GdkEventButton *) { + transport_loop (); return TRUE; + } + gint mouse_transport_play_selection (GdkEventButton *) { + transport_play_selection (); return TRUE; + } + + gint mouse_transport_roll (GdkEventButton *); + gint mouse_transport_stop (GdkEventButton *); + + void set_transport_sensitivity (bool); + + void remove_last_capture (); + + void transport_goto_start (); + void transport_goto_end (); + void transport_stop (); + void transport_stop_and_forget_capture (); + void transport_record (); + void transport_roll (); + void transport_play_selection(); + void transport_forward (int option); + void transport_rewind (int option); + void transport_loop (); + + void transport_locating (); + void transport_rolling (); + void transport_rewinding (); + void transport_forwarding (); + void transport_stopped (); + + void send_all_midi_feedback (); + + bool _session_is_new; + void connect_to_session (ARDOUR::Session *); + void connect_dependents_to_session (ARDOUR::Session *); + void we_have_dependents (); + void setup_keybindings (); + + guint32 last_key_press_time; + + void snapshot_session (); + + void map_control_change (ARDOUR::Session::ControlType); + void queue_map_control_change (ARDOUR::Session::ControlType); + void map_record_state (); + void queue_map_record_state (); + + Mixer_UI *mixer; + int create_mixer (); + + PublicEditor *editor; + int create_editor (); + + MeterBridge *meter_bridge; + int create_meter_bridge (); + + RouteParams_UI *route_params; + int create_route_params (); + + ConnectionEditor *connection_editor; + int create_connection_editor (); + + LocationUI *location_ui; + int create_location_ui (); + + void meter_bridge_hiding (); + void location_ui_hiding (); + void big_clock_hiding (); + void route_params_hiding (); + void connection_editor_hiding (); + void sfdb_hiding (); + void option_hiding (); + + /* Various options */ + + void toggle_recording_plugins (); + + /* Options window */ + + OptionEditor *option_editor; + + /* route dialog */ + + AddRouteDialog *add_route_dialog; + void add_route_dialog_done (int status); + + /* Keyboard Handling */ + + Keyboard* keyboard; + + /* Keymap handling */ + + void install_keybindings (); + void test_binding_action (const char *); + void start_keyboard_prefix(); + + void toggle_record_enable (guint32); + void toggle_monitor_enable (guint32); + + uint32_t rec_enabled_diskstreams; + void count_recenabled_diskstreams (ARDOUR::DiskStream&); + + About* about; + bool shown_flag; + /* cleanup */ + + Gtk::MenuItem *cleanup_item; + + void display_cleanup_results (ARDOUR::Session::cleanup_report& rep, const gchar* list_title, string msg); + void cleanup (); + void flush_trash (); + + bool have_configure_timeout; + struct timeval last_configure_time; + gint configure_timeout (); + + struct timeval last_peak_grab; + struct timeval last_shuttle_request; + + void cannot_record_no_input (ARDOUR::DiskStream*); + + void delete_sources_in_the_right_thread (list*); + + void editor_display_control_changed (Editing::DisplayControl c); + + bool have_disk_overrun_displayed; + bool have_disk_underrun_displayed; + + void disk_overrun_message_gone (); + void disk_underrun_message_gone (); + void disk_overrun_handler (); + void disk_underrun_handler (); + + int pending_state_dialog (); + + void disconnect_from_jack (); + void reconnect_to_jack (); + void set_jack_buffer_size (jack_nframes_t); + + Gtk::MenuItem* jack_disconnect_item; + Gtk::MenuItem* jack_reconnect_item; + Gtk::Menu* jack_bufsize_menu; + + int make_session_clean (); +}; + +#endif /* __ardour_gui_h__ */ diff --git a/gtk2_ardour/ardour_ui.rc b/gtk2_ardour/ardour_ui.rc new file mode 100644 index 0000000000..7e2edfd19a --- /dev/null +++ b/gtk2_ardour/ardour_ui.rc @@ -0,0 +1,1976 @@ +# +# This is the GTK style file for Ardour +# +# + +style "very_small_text" +{ + fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*" +} + +style "small_text" +{ + fontset="-*-helvetica-medium-r-normal-*-10-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-100-*-*-p-*-*" +} + +style "small_bold_text" +{ + fontset="-*-helvetica-bold-r-normal-*-10-*-*-*-p-*-*-*" + font ="-*-helvetica-bold-r-normal-*-*-100-*-*-p-*-*" +} + +style "medium_bold_text" +{ + fontset="-*-helvetica-bold-r-normal-*-12-*-*-*-p-*-*-*" + font ="-*-helvetica-bold-r-normal-*-*-120-*-*-p-*-*" +} + +style "medium_text" +{ + fontset="-*-helvetica-medium-r-normal-*-12-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-120-*-*-p-*-*" +} + +style "red_medium_text" = "medium_text" +{ + fg[NORMAL] = { 1.0, 0, 0 } + fg[ACTIVE] = { 1.0, 0, 0 } + fg[SELECTED] = { 1.0, 0, 0 } +} + + +style "large_text" +{ + fontset="-*-helvetica-bold-r-normal-*-18-*-*-*-p-*-*-*" + font ="-*-helvetica-bold-r-normal-*-*-180-*-*-p-*-*" +} + +style "larger_bold_text" +{ + fontset="-*-helvetica-bold-r-normal-*-14-*-*-*-p-*-*-*" + font ="-*-helvetica-bold-r-normal-*-*-140-*-*-p-*-*" +} + +style "plugin_name_text" +{ + fontset="-*-helvetica-bold-o-*-*-25-*-*-*-p-*-*-*" + font="-*-helvetica-bold-o-*-*-25-*-*-*-p-*-*-*" + fg[NORMAL] = { 0.80, 0.80, 0.70 } +} + +style "plugin_maker_text" +{ + fontset="-*-helvetica-bold-o-*-*-14-*-*-*-p-*-*-*" + font="-*-helvetica-bold-o-*-*-14-*-*-*-p-*-*-*" + fg[NORMAL] = { 0.80, 0.80, 0.70 } +} + +style "first_action_message" +{ + font="-*-helvetica-medium-r-*-*-34-350-*-*-*-*-*-*" + fontset="-*-helvetica-medium-r-*-*-34-350-*-*-*-*-*-*" +} + +style "verbose_canvas_cursor" +{ + font="-*-helvetica-medium-r-*-*-*-240-*-*-*-*-*-*" + fontset="-*-helvetica-medium-r-*-*-*-240-*-*-*-*-*-*" +} + +style "marker_text" +{ + font="-*-helvetica-medium-r-*-*-10-*-*-*-*-*-*-*" + fontset="-*-helvetica-medium-r-*-*-10-*-*-*-*-*-*-*" +} + +style "time_axis_view_item_name" +{ + font="-*-helvetica-medium-r-normal-*-*-100-*-*-p-*-*-1" + fontset="-*-helvetica-medium-r-normal-*-*-100-*-*-p-*-*-1" +} + +style "default_base" = "medium_text" +{ + fg[NORMAL] = { 0.80, 0.80, 0.70 } + fg[ACTIVE] = { 0.80, 0.80, 0.70 } + fg[PRELIGHT] = { 0.98, 0.76, 0.14 } + fg[INSENSITIVE] = { 0.80, 0.80, 0.70 } + fg[SELECTED] = {0.20, 0.90,.20 } + + bg[NORMAL] = { 0.20, 0.20, 0.20 } + bg[ACTIVE] = { 0.20, 0.20, 0.20 } + bg[PRELIGHT] = { 0.20, 0.20, 0.20 } + bg[INSENSITIVE] = { 0.10, 0.10, 0.10 } + bg[SELECTED] = { 0, 0.40, 0.60 } + + text[NORMAL] = { 0.80, 0.80, 0.70 } + text[ACTIVE] = { 0.80, 0.80, 0.70 } + text[PRELIGHT] = { 0, 0.80, 0 } + text[INSENSITIVE] = { 0.80, 0.80, 0.70 } + text[SELECTED] = { 0, 1.0, 0 } + + base[NORMAL] = { 0.0, 0.0, 0.0 } + base[ACTIVE] = { 0.0, 0.0, 0.0 } + base[PRELIGHT] = { 0.0, 0.0, 0.0 } + base[INSENSITIVE] = { 0.0, 0.0, 0.0 } + base[SELECTED] = { 0.0, 0.0, 0.0 } +} + +style "ardour_frames" = "medium_text" +{ + fg[NORMAL] = { 0.80, 0.80, 0.70 } + fg[ACTIVE] = { 0.80, 0.80, 0.70 } + fg[PRELIGHT] = { 0.98, 0.76, 0.14 } + fg[INSENSITIVE] = { 0.80, 0.80, 0.70 } + fg[SELECTED] = { 0.80, 0.80, 0.70 } + + bg[NORMAL] = { 0.80, 0.80, 0.70 } + bg[ACTIVE] = { 0.80, 0.80, 0.70 } + bg[PRELIGHT] = { 0.98, 0.76, 0.14 } + bg[INSENSITIVE] = { 0.80, 0.80, 0.70 } + bg[SELECTED] = { 0.80, 0.80, 0.70 } + + text[NORMAL] = { 0.80, 0.80, 0.70 } + text[ACTIVE] = { 0.80, 0.80, 0.70 } + text[PRELIGHT] = { 0.80, 0.80, 0.70 } + text[INSENSITIVE] = { 0.80, 0.80, 0.70 } + text[SELECTED] = { 0, 0, 0 } + + base[NORMAL] = { 0.00, 0.00, 0.00 } + base[ACTIVE] = { 0.00, 0.00, 0.00 } + base[PRELIGHT] = { 0.00, 0.00, 0.00 } + base[INSENSITIVE] = { 0.00, 0.00, 0.00 } + base[SELECTED] = { 0.00, 0.00, 0.00 } +} + +style "base_frame" +{ + fg[NORMAL] = { 0.80, 0.80, 0.70 } + bg[NORMAL] = { 0.40, 0.40, 0.40 } +} + +style "transport_base" = "medium_bold_text" +{ + bg[NORMAL] = { 0.10, 0.10, 0.10 } + bg[ACTIVE] = { 0, 0, 0 } + bg[PRELIGHT] = { 0, 0, 0 } + bg[INSENSITIVE] = { 0, 0, 0 } + bg[SELECTED] = { 0, 0, 0 } +} + +style "black_mackie_menu_bar" = "medium_bold_text" +{ + fg[NORMAL] = { 1.0, 1.0, 1.0 } + bg[NORMAL] = { 0, 0, 0 } +} + +style "default_buttons_menus" = "default_base" +{ + fontset="-*-helvetica-medium-r-normal-*-12-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-120-*-*-p-*-*" + + fg[ACTIVE] = { 0, 0, 0 } + + bg[NORMAL] = { 0.35, 0.35, 0.35 } + bg[ACTIVE] = { 0.98, 0.76, 0.14 } + bg[PRELIGHT] = { 0.25, 0.25, 0.25 } + bg[INSENSITIVE] = { 0.10, 0.10, 0.10 } + bg[SELECTED] = { 0.06, 0.06, 0.06 } +} + +style "very_small_button" = "default_buttons_menus" +{ + fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*" +} + +style "small_button" = "default_buttons_menus" +{ + fontset="-*-helvetica-medium-r-normal-*-10-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-100-*-*-p-*-*" +} + +style "very_small_red_active_and_selected_button" = "very_small_button" +{ + bg[ACTIVE] = { 1.0, 0, 0} + bg[SELECTED] = { 1.0, 0, 0} +} + +style "small_red_active_and_selected_button" = "small_button" +{ + fg[ACTIVE] = { 0, 0, 0 } + bg[ACTIVE] = { 1.0, 0, 0} + bg[SELECTED] = { 1.0, 0, 0} +} + +style "track_rec_enable_button" = "small_button" +{ + fg[SELECTED] = { 0.0, 0.0, 0.0 } + fg[ACTIVE] = { 0.0, 0.0, 0.0 } + fg[PRELIGHT] = { 0.0, 0.0, 0.0 } + + bg[SELECTED] = { 1.0, 0.0, 0.0 } + bg[ACTIVE] = { 0.91, 0.68, 0.68} + bg[PRELIGHT] = { 1.0, 0.0, 0.0 } +} + +style "mixer_rec_enable_button" = "track_rec_enable_button" +{ + fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*" +} + +style "solo_button" = "small_button" +{ + bg[PRELIGHT] = { 0, 1.0, 0 } + bg[ACTIVE] = { 0.66, 0.97, 0.19 } + + fg[PRELIGHT] = { 0, 0, 0 } + fg[ACTIVE] = { 0, 0, 0 } +} + +style "mixer_solo_button" = "solo_button" +{ + fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*" +} + + +style "mute_button" = "small_button" +{ + bg[PRELIGHT] = { 1.0, 0.65, 0.13 } + bg[ACTIVE] = { 1.0, 0.98, 0.53 } + + fg[PRELIGHT] = { 0, 0, 0 } +} + +style "mixer_mute_button" = "mute_button" +{ + fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*" +} + +style "track_loop_button" = "small_button" +{ + bg[ACTIVE] = { 1.0, 0.98, 0.53 } + bg[PRELIGHT] = { 1.0, 0.98, 0.53 } + +} + +style "mixer_red_active_button" = "very_small_button" +{ + fg[ACTIVE] = { 0, 1.0, 1.0 } + bg[ACTIVE] = { 0.7, 0, 0 } + + base[INSENSITIVE] = { 0.21, 0.21, 0.21 } + bg[INSENSITIVE] = { 0.21, 0.21, 0.21 } +} + +style "time_button" = "default_buttons_menus" +{ + fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*" +} + +style "transport_button" = "very_small_button" +{ + bg[ACTIVE] = { 0.66, 0.97, 0.18 } + bg[SELECTED] = { 1.0, 0.04, 0.04 } +} + +style "transport_rec_button" = "very_small_button" +{ + bg[ACTIVE] = { 0.82, 0.02, 0.02 } + bg[SELECTED] = { 1.0, 0.04, 0.04 } +} + +style "shuttle_control" = "very_small_text" +{ + fg[NORMAL] = { 0.85, 0.92, 0.98 } + fg[ACTIVE] = { 0.85, 0.92, 0.98 } + fg[PRELIGHT] = { 0.85, 0.92, 0.98 } + fg[SELECTED] = { 0.85, 0.92, 0.98 } + fg[INSENSITIVE] = { 0.85, 0.92, 0.98 } + + bg[NORMAL] = { 0.31, 0.31, 0.31 } + bg[PRELIGHT] = { 0.31, 0.31, 0.31 } + bg[INSENSITIVE] = { 0.31, 0.31, 0.31 } + bg[ACTIVE] = { 0.66, 0.97, 0.18 } + bg[SELECTED] = { 1.0, 0.04, 0.04 } +} + +style "ardour_adjusters" = "default_buttons_menus" +{ + bg[NORMAL] = { 0.60, 0.60, 0.60 } + bg[PRELIGHT] = { 0.80, 0.80, 0.70 } + bg[ACTIVE] = { 0.18, 0.18, 0.22 } +} + +style "ardour_progressbars" = "default_buttons_menus" +{ + bg[NORMAL] = { 0, 0, 0 } + bg[PRELIGHT] = { 0.00, 0.36, 0.40 } +} + +style "options_window" = "default_base" +{ + fontset="-*-helvetica-bold-r-normal-*-12-*-*-*-p-*-*-*" + font ="-*-helvetica-bold-r-normal-*-*-120-*-*-p-*-*" + fg[PRELIGHT] = { 0.80, 0.80, 0.70 } +} + +style "option_entry" = "default_base" +{ + fg[NORMAL] = { 0.98, 0.76, 0.14 } + fg[ACTIVE] = { 0.98, 0.76, 0.14 } + fg[INSENSITIVE] = { 0.80, 0.80, 0.70 } + + base[INSENSITIVE] = { 0.12, 0.12, 0.12 } + + bg[NORMAL] = { 0.40, 0.40, 0.40 } + bg[ACTIVE] = { 0.40, 0.40, 0.40 } +} + +style "red_when_active" = "medium_text" +{ + fg[NORMAL] = { 0.80, 0.80, 0.70 } + bg[NORMAL] = { 0.31, 0.31, 0.31 } + + fg[ACTIVE] = { 0.80, 0.80, 0.70 } + bg[ACTIVE] = { 1.0, 0, 0} +} + +style "xrun_warn" +{ + font ="-*-helvetica-bold-r-normal-*-*-180-*-*-p-*-*" + fontset="-*-helvetica-bold-r-normal-*-18-*-*-*-p-*-*-*" + + fg[NORMAL] = { 1.0, 1.0, 1.0 } + fg[ACTIVE] = { 1.0, 1.0, 1.0 } + text[NORMAL] = { 1.0, 1.0, 1.0 } + text[ACTIVE] = { 1.0, 1.0, 1.0 } + base[NORMAL] = { 0.09, 0.48, 0.46 } + base[ACTIVE] = { 0.09, 0.48, 0.46 } + bg[NORMAL] = { 1.0, 0.48, 0.46 } + bg[ACTIVE] = { 0.09, 1.0, 0.46 } +} + +style "menu_bar_base" +{ + bg[NORMAL] = { 0, 0, 0 } + bg[ACTIVE] = { 0, 0, 0 } + bg[PRELIGHT] = { 0, 0, 0 } + bg[INSENSITIVE] = { 0, 0, 0 } + bg[SELECTED] = { 0, 0, 0 } +} + +style "fatal_message" = "medium_text" +{ + fg[ACTIVE] = { 1.0, 0, 1.0 } + fg[NORMAL] = { 0.80, 0.80, 0.70 } + bg[ACTIVE] = { 0,0,0 } + bg[NORMAL] = { 0,0,0 } + base[ACTIVE] = { 0,0,0 } + base[NORMAL] = { 0,0,0 } +} + +style "error_message" = "medium_text" +{ + fg[ACTIVE] = { 1.0, 0, 0 } + fg[NORMAL] = { 0.80, 0.80, 0.70 } + bg[ACTIVE] = { 0,0,0 } + bg[NORMAL] = { 0,0,0 } + base[ACTIVE] = { 0,0,0 } + base[NORMAL] = { 0,0,0 } +} + +style "info_message" = "medium_text" +{ + fg[ACTIVE] = { 1.0, 0, 0 } + fg[NORMAL] = { 0.80, 0.80, 0.70 } + bg[ACTIVE] = { 0,0,0 } + bg[NORMAL] = { 0,0,0 } + base[ACTIVE] = { 0,0,0 } + base[NORMAL] = { 0,0,0 } +} + +style "warning_message" = "medium_text" +{ + fg[ACTIVE] = { 0.30,0.30, 1.0 } + fg[NORMAL] = { 0.80, 0.80, 0.70 } + bg[ACTIVE] = { 0, 0, 0 } + bg[NORMAL] = { 0, 0, 0 } + base[ACTIVE] = { 0, 0, 0 } + base[NORMAL] = { 0, 0, 0 } +} + +style "medium_entry" = "medium_text" +{ + fg[NORMAL] = { 0.98, 0.76, 0.14 } + fg[ACTIVE] = { 0.98, 0.76, 0.14 } + fg[SELECTED] = { 0.66, 0.97, 0.18 } + + bg[NORMAL] = { 0.40, 0.40, 0.40 } + + base[NORMAL] = { 0, 0, 0 } + base[ACTIVE] = { 0, 0, 0 } + base[SELECTED] = { 0, 0, 0 } +} + +style "medium_entry_noselection_fg" = "medium_entry" +{ + fg[SELECTED] = { 0.98, 0.76, 0.14 } +} + +style "medium_entry_noselection_bg" = "medium_entry" +{ + bg[SELECTED] = { 0, 0, 0 } +} + +style "medium_bold_entry" = "medium_bold_text" +{ + fg[NORMAL] = { 0.98, 0.76, 0.14 } + fg[ACTIVE] = { 0.98, 0.76, 0.14 } + + bg[NORMAL] = { 0.40, 0.40, 0.40 } + + base[NORMAL] = { 0, 0, 0 } + base[ACTIVE] = { 0, 0, 0 } + base[SELECTED] = { 0, 0, 0 } +} + + +style "small_entry" = "small_text" +{ + fg[NORMAL] = { 0.98, 0.76, 0.14 } + fg[ACTIVE] = { 0.98, 0.76, 0.14 } + bg[NORMAL] = { 0.0, 0.0, 0.0 } + base[NORMAL] = { 0, 0, 0 } + base[ACTIVE] = { 0, 0, 0 } + base[SELECTED] = { 0, 0, 0 } +} + +style "red_active_small_entry" = "small_entry" +{ + fg[ACTIVE] = { 1.0, 0.0, 0.0 } + fg[SELECTED] = { 1.0, 0, 0 } +} + +style "small_bold_entry" = "small_bold_text" +{ + fg[NORMAL] = { 0.98, 0.76, 0.14 } + fg[ACTIVE] = { 0.98, 0.76, 0.14 } + + bg[NORMAL] = { 0.40, 0.40, 0.40 } + + base[NORMAL] = { 0, 0, 0 } + base[ACTIVE] = { 0, 0, 0 } + base[SELECTED] = { 0, 0, 0 } +} + +style "small_red_on_black_entry" = "small_bold_text" +{ + fg[NORMAL] = { 1.0, 0, 0 } + fg[ACTIVE] = { 1.0, 0, 0 } + base[NORMAL] = { 0.0, 0.0, 0.0 } + base[ACTIVE] = { 0.0, 0.0, 0.0 } + bg[NORMAL] = { 0.0, 0.0, 0.0 } + bg[ACTIVE] = { 0.0, 0.0, 0.0 } +} + +style "big_clock_display" = "medium_entry" +{ + fontset = "-*-courier-bold-r-*-*-34-*-*-*-*-*-*-*" + font = "-*-courier-bold-r-*-*-34-*-*-*-*-*-*-*" +} + +style "transport_clock_display" +{ + fontset = "-*-helvetica-bold-r-*-*-18-*-*-*-*-*-*-*" + font = "-*-helvetica-bold-r-*-*-18-*-*-*-*-*-*-*" + + fg[NORMAL] = { 0.66, 0.97, 0.18 } + fg[ACTIVE] = { 1.0, 0, 0.0 } + fg[SELECTED] = { 1.0, 0, 0 } + fg[PRELIGHT] = { 1.0, 0, 0.0 } + fg[INSENSITIVE] = { 1.0, 0, 0.0 } + + base[NORMAL] = { 0.0, 0.0, 0.0 } + base[ACTIVE] = { 0.0, 0.0, 0.0 } + bg[NORMAL] = { 0.0, 0.0, 0.0 } + bg[ACTIVE] = { 0.0, 0.0, 0.0 } +} + +style "tempo_meter_clock_display" +{ + fontset = "-*-helvetica-bold-r-*-*-8-*-*-*-*-*-*-*" + font = "-*-helvetica-bold-r-*-*-8-*-*-*-*-*-*-*" + fg[NORMAL] = { 1.0, 1.0, 1.0 } + fg[ACTIVE] = { 1.0, 1.0, 0.0 } + fg[SELECTED] = { 1.0, 0, 0 } + base[NORMAL] = { 0.0, 0.48, 1.0 } + base[ACTIVE] = { 0.09, 0.98, 0.46 } + bg[NORMAL] = { 0.0, 0.48, 1.0 } + bg[ACTIVE] = { 0.09, 0.98, 0.46 } +} + +style "default_clock_display" = "medium text" +{ + fg[NORMAL] = { 0.98, 0.76, 0.14 } + fg[ACTIVE] = { 1.0, 0.0, 0.0 } + fg[SELECTED] = { 1.0, 0, 0 } + base[NORMAL] = { 0, 0, 0 } + base[ACTIVE] = { 0, 0, 0 } + bg[NORMAL] = { 0, 0, 0 } + bg[ACTIVE] = { 0, 0, 0 } +} + +style "editor_time_ruler" = "small_text" +{ + fg[NORMAL] = { 0.80, 0.80, 0.70 } + bg[NORMAL] = { 0.09, 0.09, 0.09 } +} + +style "audio_track_base" = "default_base" +{ + font = "-*-courier-medium-r-*-*-*-100-*-*-*-*-*-*" + fg[NORMAL] = { 0.80, 0.80, 0.70 } + bg[NORMAL] = { 0.18, 0.18, 0.22 } + bg[ACTIVE] = { 0.20, 0.20, 0.20 } + bg[PRELIGHT] = { 0.20, 0.20, 0.20 } + bg[INSENSITIVE] = { 0.20, 0.20, 0.20 } + bg[SELECTED] = { 0.20, 0.20, 0.20 } +} + +style "audio_bus_base" +{ + font = "-*-courier-medium-r-*-*-*-100-*-*-*-*-*-*" + fg[NORMAL] = { 0.7, 0.8, 0.2 } + bg[NORMAL] = {0, 0.36, 0.40 } +} + +style "track_name_display" +{ + font = "-*-helvetica-medium-r-*-*-*-100-*-*-*-*-*-*" + fg[NORMAL] = { 0.80, 0.80, 0.70 } + fg[ACTIVE] = { 0.80, 0.80, 0.70 } + + base[NORMAL] = { 0.06, 0.06, 0.06 } + base[ACTIVE] = { 0.26, 0.26, 0.26 } + bg[NORMAL] = { 0.26, 0.26, 0.26 } + bg[ACTIVE] = { 0.26, 0.26, 0.26 } +} + +style "track_separator" +{ + bg[NORMAL] = { 0.40, 0.40, 0.40 } +} + +# +# Track edit groups. These styles define +# the colors that the "edit" button will +# use as a track is moved from +# track edit group to track edit group. +# There are 8 edit groups. Edit group 0 +# is used for tracks that are not editable, +# so we leave its style to the default. +# + +style "edit_group_0" + +{ + bg[ACTIVE] = { 1.0, 0.65, 0.13 } + bg[NORMAL] = { 0.31, 0.31, 0.31 } + fg[NORMAL] = { 0.82, 0.91, 0.99 } + fg[ACTIVE] = { 0, 0, 0 } +} + +style "edit_group_1" +{ + fg[NORMAL] = { 0, 0, 0 } + fg[PRELIGHT] = { 0, 0, 0 } + fg[SELECTED] = { 0, 0, 0 } + bg[NORMAL] = { 0.93, 0.34, 0.08 } + bg[PRELIGHT] = { 0.93, 0.34, 0.08 } + bg[SELECTED] = { 0.93, 0.34, 0.08 } +} + +style "edit_group_2" +{ + fg[NORMAL] = { 0, 0, 0 } + fg[PRELIGHT] = { 0, 0, 0 } + fg[SELECTED] = { 0, 0, 0 } + bg[NORMAL] = { 0.93, 0.34, 0.08 } + bg[PRELIGHT] = { 0.93, 0.34, 0.08 } + bg[SELECTED] = { 0.93, 0.34, 0.08 } +} + +style "edit_group_3" +{ + fg[NORMAL] = { 0, 0, 0 } + fg[PRELIGHT] = { 0, 0, 0 } + fg[SELECTED] = { 0, 0, 0 } + bg[NORMAL] = { 0.93, 0.34, 0.08 } + bg[PRELIGHT] = { 0.93, 0.34, 0.08 } + bg[SELECTED] = { 0.93, 0.34, 0.08 } +} + +style "region_list_display" = "small_bold_text" +{ + fg[NORMAL] = { 0.80, 0.80, 0.70 } + fg[ACTIVE] = { 0.80, 0.80, 0.70 } + fg[SELECTED] = { 0.98, 0.76, 0.14 } + bg[NORMAL] = { 0, 0, 0 } + bg[ACTIVE] = { 0, 0, 0 } + bg[SELECTED] = { 0, 0, 0 } + base[NORMAL] = { 0, 0, 0 } + base[ACTIVE] = { 0, 1, 0 } + base[INSENSITIVE] = { 0, 0, 0 } + base[SELECTED] = { 0.80, 0.80, 0.70 } +} + +style "main_canvas_area" +{ + bg[NORMAL] = { 0.38, 0.38, 0.38 } + bg[ACTIVE] = { 0.38, 0.38, 0.38 } + bg[INSENSITIVE] = { 0.38, 0.38, 0.38 } + bg[SELECTED] = { 0.38, 0.38, 0.38 } + bg[PRELIGHT] = { 0.38, 0.38, 0.38 } +} + +style "track_controls_inactive" +{ + bg[NORMAL] = { 0.60, 0.60, 0.66 } + bg[ACTIVE] = { 0.60, 0.60, 0.66 } + bg[INSENSITIVE] = { 0.60, 0.60, 0.66 } + bg[SELECTED] = { 0.60, 0.60, 0.66 } + bg[PRELIGHT] = { 0.60, 0.60, 0.66 } + + font = "-*-courier-medium-r-*-*-*-100-*-*-*-*-*-*" + fg[NORMAL] = { 0.7, 0.8, 0.2 } +} + +style "edit_controls_base_selected" +{ + bg[NORMAL] = { 0.56, 0.56, 0.56 } + bg[ACTIVE] = { 0.56, 0.56, 0.56 } + bg[INSENSITIVE] = { 0.56, 0.56, 0.56 } + bg[SELECTED] = { 0.56, 0.56, 0.56 } + bg[PRELIGHT] = { 0.56, 0.56, 0.56 } +} + +style "automation_track_controls_base" +{ + bg[NORMAL] = { 0.22, 0.22, 0.29 } + bg[ACTIVE] = { 0.22, 0.22, 0.29 } + bg[INSENSITIVE] = { 0.22, 0.22, 0.29 } + bg[SELECTED] = { 0.22, 0.22, 0.29 } + bg[PRELIGHT] = { 0.22, 0.22, 0.29 } +} + +# Plugin Editors +style "plugin_slider" +{ + fontset="-*-helvetica-medium-r-normal-*-10-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-100-*-*-p-*-*" + + fg[NORMAL] = { 0.45, 0.45, 0.45 } + fg[ACTIVE] = { 0.45, 0.45, 0.45 } + fg[INSENSITIVE] = {0.0, 0.0, 0.0 } # matches default_base + fg[SELECTED] = { 0.45, 0.45, 0.45 } + fg[PRELIGHT] = { 0.45, 0.45, 0.45 } + + text[NORMAL] = { 0.80, 0.80, 0.70 } + text[ACTIVE] = { 0.80, 0.80, 0.70 } + text[INSENSITIVE] = { 0.80, 0.80, 0.70 } + text[SELECTED] = { 0.80, 0.80, 0.70 } + text[PRELIGHT] = { 0.80, 0.80, 0.70 } +} + +style "track_list_display" = "small_bold_text" +{ + fg[NORMAL] = { 0.80, 0.80, 0.70 } + fg[ACTIVE] = { 0.80, 0.80, 0.70 } + fg[SELECTED] = { 0.98, 0.76, 0.14 } + bg[NORMAL] = { 0, 0, 0 } + bg[ACTIVE] = { 0, 0, 0 } + bg[SELECTED] = { 0, 0, 0 } + base[NORMAL] = { 0, 0, 0 } + base[ACTIVE] = { 0, 0, 0 } + base[INSENSITIVE] = { 0, 0, 0 } + base[SELECTED] = { 0, 0, 0 } +} + +style "region_list_display" = "small_bold_text" +{ + fg[NORMAL] = { 0.98, 0.76, 0.14 } + fg[ACTIVE] = { 0.98, 0.76, 0.14 } + fg[SELECTED] = { 0.66, 0.97, 0.18 } + bg[NORMAL] = { 0, 0, 0 } + bg[ACTIVE] = { 0, 0, 0 } + bg[SELECTED] = { 0, 0, 0 } + base[NORMAL] = { 1, 0, 0 } + base[ACTIVE] = { 0, 0, 0 } + base[INSENSITIVE] = { 0, 0, 0 } + base[SELECTED] = { 0, 0, 0 } +} + +# MixerPanZone: +# +# the NORMAL fg color is used for the pan puck +# the ACTIVE fg color is used for the speaker boxes + +style "pan_zone" = "default_base" +{ + fg[NORMAL] = { 0.34, 0.95, 0.92 } + fg[ACTIVE] = { 0.95, 0.48, 0.11 } +} + +style "wall_clock" = "medium_bold_text" +{ + fg[NORMAL] = { 1.0, 1.0, 1.0 } + bg[NORMAL] = { 0, 0, 0 } +} + +style "paler_red_when_active" = "medium_text" +{ + fg[NORMAL] = { 0.80, 0.80, 0.70 } + fg[PRELIGHT] = { 0.80, 0.80, 0.70 } + bg[NORMAL] = { 0.31, 0.31, 0.31 } + bg[PRELIGHT] = { 0.31, 0.31, 0.31 } + + fg[ACTIVE] = { 0.36, 0.46, 0.28 } + bg[ACTIVE] = { 1.00, 0.59, 0.59} +} + +style "peak_display_peaked_entry" = "small_text" +{ + fg[NORMAL] = { 1.0, 1.0, 1.0 } + fg[ACTIVE] = { 1.0, 1.0, 1.0 } + fg[SELECTED] = { 1.0, 1.0, 1.0 } + + bg[NORMAL] = {0.9, 0.0, 0.0 } + bg[ACTIVE] = { 0.9, 0.0, 0.0 } + bg[PRELIGHT] = { 0.9, 0.0, 0.0 } + bg[INSENSITIVE] = { 0.9, 0.0, 0.0 } + bg[SELECTED] = { 0.9, 0.0, 0.0 } + base[NORMAL] = { 0.9, 0.0, 0.0 } + base[ACTIVE] = { 0.9, 0.0, 0.0 } + base[PRELIGHT] = { 0.9, 0.0, 0.0 } + base[INSENSITIVE] = { 0.9, 0.0, 0.0 } + base[SELECTED] = { 0.9, 0.0, 0.0 } +} + +style "selected_strip_frame" +{ + fg[NORMAL] = { 0.74, 0.42, 0.47 } + bg[NORMAL] = { 0.79, 0.28, 0.18 } +} + +style "flashing_alert" = "very_small_text" +{ + fg[NORMAL] = { 0.80, 0.80, 0.70 } + bg[NORMAL] = { 0.31, 0.31, 0.31 } + + fg[ACTIVE] = { 0.80, 0.80, 0.70 } + bg[ACTIVE] = { 1.0, 0, 0} +} + +style "selected_io_selector_port_list" = "medium_text" +{ + fg[NORMAL] = { 0.98, 0.76, 0.14 } + fg[SELECTED] = { 0.98, 0.76, 0.14 } + base[NORMAL] = { 0, 0, 0 } + base[SELECTED] = { 0, 0, 0 } +} + +style "io_selector_port_list" = "medium_text" +{ + fg[NORMAL] = {0.80, 0.80, 0.70 } + fg[SELECTED] = {0.80, 0.80, 0.70 } + base[NORMAL] = { 0.26, 0.26, 0.26 } + base[SELECTED] = { 0.26, 0.26, 0.26 } +} + +style "io_selector_notebook" = "default_base" +{ + fg[NORMAL] = { 0.98, 0.76, 0.14 } + font ="-*-helvetica-bold-r-normal-*-*-140-*-*-p-*-*" +} + +style "tearoff_arrow" = "medium_bold_entry" +{ + bg[NORMAL] = { 0.80, 0.80, 0.70 } + bg[PRELIGHT] = { 0.98, 0.76, 0.14 } +} + +style "meter_metrics_strip" = "default_base" +{ + font = "-*-courier-medium-r-*-*-*-100-*-*-*-*-*-*" + fg[NORMAL] = { 0.7, 0.8, 0.2 } +} + +style "no_session_msg" +{ + font = "-*-helvetica-medium-r-*-*-34-350-*-*-*-*-*-*" +} + +style "location_row_button" = "default_buttons_menus" +{ + fontset="-*-helvetica-medium-r-normal-*-10-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-100-*-*-p-*-*" +} + +style "location_rows_clock" = "default_clock_display" +{ + fontset="-*-helvetica-medium-r-normal-*-12-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-120-*-*-p-*-*" +} + +style "pan_slider" +{ + fontset="-*-helvetica-medium-r-normal-*-8-*-*-*-p-*-*-*" + font ="-*-helvetica-medium-r-normal-*-*-80-*-*-p-*-*" + + fg[NORMAL] = { 0.67, 0.23, 0.22 } + fg[ACTIVE] = { 0.67, 0.23, 0.22 } + fg[INSENSITIVE] = {0.32, 0.39, 0.45 } # matches default_base + fg[SELECTED] = { 0.67, 0.23, 0.22 } + fg[PRELIGHT] = { 0.67, 0.23, 0.22 } + + bg[NORMAL] = { 0, 0, 0 } + bg[ACTIVE] = { 0, 0, 0 } + bg[INSENSITIVE] = {0.32, 0.39, 0.45 } # matches default_base + bg[SELECTED] = { 0, 0, 0 } + bg[PRELIGHT] = { 0, 0, 0 } + + text[NORMAL] = { 0.85, 0.92, 0.98 } + text[ACTIVE] = { 0.85, 0.92, 0.98 } + text[INSENSITIVE] = { 0.85, 0.92, 0.98 } + text[SELECTED] = { 0.85, 0.92, 0.98 } + text[PRELIGHT] = { 0.85, 0.92, 0.98 } +} + +#--------------------------------------------------------------- +widget "*FirstActionMessage" style "first_action_message" +widget "*VerboseCanvasCursor" style "verbose_canvas_cursor" +widget "*MarkerText" style "marker_text" +widget "*TimeAxisViewItemName" style "time_axis_view_item_name" +widget "EditorBase" style "default_base" +widget "*TimebarLabelBase" style "default_base" +widget "*WipeWindow" style "default_base" +widget "*TakeWindow" style "default_base" +widget "*TrackCanvasScroller" style "default_base" +widget "*TimeCanvasScroller" style "default_base" +widget "*SendUIWindow" style "default_base" +widget "*SendUIFrame" style "default_base" +widget "*MouseModeBase" style "default_base" +widget "*SelectionModeBase" style "default_base" +widget "*MeterBridgeWindow" style "default_base" +widget "*ControlWindow" style "default_base" +widget "*RegionWindow" style "default_base" +widget "*ClickWindow" style "default_base" +widget "*RegionRenameWindow" style "default_base" +widget "*BackupRecoveryWindow" style "default_base" +widget "*PluginDisplayWindow" style "default_base" +widget "*ExportWindow" style "default_base" +#widget "*ExportProgress" style "default_buttons_menus" +widget "*ExportFileLabel" style "small_bold_text" +widget "*ExportFormatLabel" style "medium_bold_text" +widget "*ExportHeader" style "small_bold_text" +widget "*ExportFileDisplay" style "medium_entry" +widget "*ExportFormatDisplay" style "medium_entry" +widget "*ExportCheckbox" style "small_entry" +widget "*ExportTrackSelector" style "medium_entry_noselection_bg" +widget "*MeterScrollBase" style "default_base" +widget "*MixerWindow" style "default_base" +widget "*RegionEditorWindow" style "default_base" +widget "*AudioEngineControl" style "default_base" +widget "*PeakFileWaitWindow" style "default_base" +widget "*OptionsWindow" style "default_base" +widget "*TimeStretchDialog" style "default_base" +widget "*ChoiceWindow" style "default_base" +widget "*PluginManagerWindow" style "default_base" +widget "*CrossfadeEditWindow" style "default_base" +widget "*ErrorText" style "default_base" +widget "*LocationWindow" style "default_base" +widget "*EditControlsBase" style "default_base" +widget "*ToolBar" style "default_base" +widget "*EditModeSelector" style "medium_bold_entry" +widget "*SnapTypeSelector" style "medium_bold_entry" +widget "*SnapModeSelector" style "medium_bold_entry" +widget "*ZoomFocusSelector" style "medium_bold_entry" +widget "*BigClockBase" style "default_base" +widget "*AboveMeterZone" style "default_base" +widget "*BelowMeterZone" style "default_base" +widget "*ButtonTable" style "default_base" +widget "*AdjusterTable" style "default_base" +widget "*PluginEditor" style "default_base" +widget "*PluginNameBox" style "default_base" +widget "*IOSelectorWindow" style "default_base" +widget "*ConnectionEditorWindow" style "default_base" +widget "*RouteParamsWindow" style "default_base" +widget "*RouteParamsBaseFrame" style "default_base" +widget "*MetricDialog" style "default_base" +widget "AddRouteDialog" style "default_base" +widget "*LocationLocRowsScroller*" style "default_base" +widget "*LocationRangeRowsScroller*" style "default_base" +widget "*LocationRangeRows" style "default_base" +widget "*LocationLocRows" style "default_base" +widget "*LocationFrameBox" style "default_base" +widget "*PanScrollerBase" style "default_base" +widget "*ArdourContextMenu*" style "default_buttons_menus" +widget "*EditGroupTitleButton*" style "default_buttons_menus" +widget "*MixerGroupTitleButton*" style "default_buttons_menus" +widget "*ErrorLogCloseButton" style "default_buttons_menus" +widget "*EditorGTKButton*" style "default_buttons_menus" +widget "*ToolbarButton" style "default_buttons_menus" +widget "*ToolbarButton*" style "default_buttons_menus" +widget "*CrossfadeEditButton" style "default_buttons_menus" +widget "*CrossfadeEditButton*" style "default_buttons_menus" +widget "*TrackHistoryButton*" style "default_buttons_menus" +widget "*TrackSizeButton*" style "default_buttons_menus" +widget "*TrackPlaylistButton*" style "default_buttons_menus" +widget "*TrackAutomationButton*" style "default_buttons_menus" +widget "*TrackGroupButton*" style "default_buttons_menus" +widget "*TrackMixButton*" style "default_buttons_menus" +widget "*TrackVisualButton*" style "default_buttons_menus" +widget "*TrackRemoveButton*" style "default_buttons_menus" +widget "*BaseButton" style "default_buttons_menus" +widget "*TakeButtonLabel" style "default_buttons_menus" +widget "*MixerWidthButton" style "default_buttons_menus" +widget "*MixerHideButton" style "default_buttons_menus" +widget "*MixerSendButton" style "default_buttons_menus" +widget "*MixerSendButtonLabel" style "default_buttons_menus" +widget "*MixerSendSwitch" style "default_buttons_menus" +widget "*MixerInsertButton" style "default_buttons_menus" +widget "*MixerInsertButtonLabel" style "default_buttons_menus" +widget "*MixerInsertSwitch" style "default_buttons_menus" +widget "*MixerMonitorInputButton*" style "very_small_button" +widget "*MixerMonitorInputButton.*" style "very_small_button" +widget "*MixerIOButton" style "very_small_button" +widget "*MixerIOButtonLabel" style "very_small_button" +widget "*AddRouteDialogSpinner" style "ardour_adjusters" +widget "*AddRouteDialogRadioButton*" style "options_window" +widget "*OptionsNotebook" style "options_window" +widget "*OptionEditorToggleButton*" style "options_window" +widget "*OptionsLabel" style "options_window" +widget "*OptionEditorAuditionerLabel" style "options_window" +widget "*OptionsEntry" style "option_entry" +widget "*InspectorNotebook" style "options_window" +widget "*NewSessionDialog" style "options_window" +widget "*NewSessionDialogButton*" style "options_window" +widget "*MixerSendSwitch*" style "very_small_red_active_and_selected_button" +widget "*OptionEditorToggleButton" style "small_red_active_and_selected_button" +widget "*NewSessionDialogButton" style "small_red_active_and_selected_button" +widget "*MixerRecordEnableButton" style "mixer_rec_enable_button" +widget "*MixerRecordEnableButton*" style "mixer_rec_enable_button" +widget "*TrackRecordEnableButton" style "track_rec_enable_button" +widget "*TrackRecordEnableButton*" style "track_rec_enable_button" +widget "*TrackMuteButton*" style "mute_button" +widget "*TrackLoopButton*" style "track_loop_button" +widget "*EditorTimeButton*" style "time_button" +widget "*EditorMixerButton*" style "default_buttons_menus" +widget "*SoloButton*" style "solo_button" +widget "*SoloButton.*" style "solo_button" +widget "*SafeSoloButton*" style "solo_button" +widget "*SafeSoloButton.*" style "solo_button" +widget "*MixerPhaseInvertButton*" style "very_small_button" +widget "*MixerPhaseInvertButton.*" style "very_small_button" +widget "*MixerAutomationRecordingButton*" style "very_small_button" +widget "*MixerAutomationRecordingButton.*" style "very_small_button" +widget "*MixerAutomationModeButton*" style "very_small_button" +widget "*MixerAutomationModeButton.*" style "very_small_button" +widget "*MixerAutomationPlaybackButton*" style "very_small_button" +widget "*MixerAutomationPlaybackButton.*" style "very_small_button" +widget "*MixerMuteButton*" style "mixer_mute_button" +widget "*MixerMuteButton.*" style "mixer_mute_button" +widget "*MixerSoloButton*" style "mixer_solo_button" +widget "*MixerSoloButton.*" style "mixer_solo_button" +widget "*MixerNameButton" style "very_small_button" +widget "*MixerNameButtonLabel" style "very_small_button" +widget "*MixerGroupButton" style "very_small_button" +widget "*MixerGroupButtonLabel" style "very_small_button" +widget "*MixerCommentButton" style "very_small_button" +widget "*MixerCommentButton*" style "very_small_button" +widget "*EditGroupButton" style "very_small_button" +widget "*EditGroupButtonLabel" style "very_small_button" +widget "*TransportButton" style "transport_button" +widget "*TransportButton*" style "transport_button" +widget "*ShuttleButton" style "transport_button" +widget "*ShuttleButton*" style "transport_button" +widget "*ShuttleDisplay" style "transport_button" +widget "*ShuttleDisplay*" style "transport_button" +widget "*ShuttleControl" style "shuttle_control" +widget "*TransportRecButton" style "transport_rec_button" +widget "*TransportRecButton*" style "transport_rec_button" +widget "*TransportBase" style "default_base" +widget "*TransportWindow" style "default_base" +widget "*RecordingXrunWarningWindow" style "xrun_warn" +widget "*RecordingXrunWarningWindow*" style "xrun_warn" +widget "*MainMenuBar" style "menu_bar_base" +widget "*ErrorMessage" style "error_message" +widget "*FatalMessage" style "fatal_message" +widget "*InfoMessage" style "info_message" +widget "*WarningMessage" style "warning_message" +widget "*BigClockDisplay" style "big_clock_display" +widget "*TransportClockDisplay" style "transport_clock_display" +widget "*SecondaryClockDisplay" style "transport_clock_display" +widget "*BBTTempoLabel" style "tempo_meter_clock_display" +widget "*BBTMeterLabel" style "tempo_meter_clock_display" +widget "*SelectionStartClock" style "default_clock_display" +widget "*SelectionEndClock" style "default_clock_display" +widget "*EditCursorClock" style "default_clock_display" +widget "*PreRollClock" style "default_clock_display" +widget "*PostRollClock" style "default_clock_display" +widget "*NudgeClock" style "default_clock_display" +widget "*ZoomRangeClock" style "default_clock_display" +widget "*SMPTEOffsetClock" style "default_clock_display" +widget "*TransportLabel" style "small_bold_text" +widget "*TakeLabel" style "small_bold_text" +widget "*LocationLabel" style "small_bold_text" +widget "*WipeLabel" style "small_bold_text" +widget "*TakeTagLabel" style "small_bold_text" +widget "*ToolBarLabel" style "small_bold_text" +widget "*EditorDisplayLabel" style "small_bold_text" +widget "*NewSessionLabel" style "large_text" +widget "*GlobalButtonLabel" style "default_buttons_menus" +widget "*ClickButton" style "medium_entry" +widget "*RegionNameDisplay" style "medium_entry" +widget "*PluginDisplay" style "medium_entry" +widget "*SelectionDisplay" style "medium_entry" +widget "*HistorySelector" style "medium_entry" +widget "*LocationSelector" style "medium_entry" +widget "*TakeSelector" style "medium_entry" +widget "*RegionSelector" style "medium_entry" +widget "*SMPTERuler" style "editor_time_ruler" +widget "*BBTRuler" style "editor_time_ruler" +widget "*FramesRuler" style "editor_time_ruler" +widget "*MinSecRuler" style "editor_time_ruler" +widget "*BaseFrame" style "base_frame" +widget "*AudioTrackStripBase" style "audio_track_base" +widget "*TimeAxisViewControlsBaseUnselected" style "audio_track_base" +widget "*AudioTrackControlsBaseUnselected" style "audio_track_base" +widget "*AudioTrackFader" style "audio_track_base" +widget "*AudioBusStripBase" style "audio_bus_base" +widget "*BusControlsBaseUnselected" style "audio_bus_base" +widget "*AudioBusFader" style "audio_bus_base" +widget "*TrackSeparator" style "track_separator" +widget "*TrackEditIndicator0*" style "edit_group_0" +widget "*TrackEditIndicator1*" style "edit_group_1" +widget "*TrackEditIndicator2*" style "edit_group_2" +widget "*TrackEditIndicator3*" style "edit_group_3" +widget "*TrackEditIndicator4*" style "edit_group_3" +widget "*TrackEditIndicator5*" style "edit_group_3" +widget "*TrackEditIndicator6*" style "edit_group_3" +widget "*TrackEditIndicator7*" style "edit_group_3" +widget "*EditorTrackNameDisplay" style "track_name_display" +widget "*EditorTrackNameDisplay*" style "track_name_display" +widget "*EditorRegionList" style "region_list_display" +widget "*CrossfadeEditAuditionButton" style "red_when_active" +widget "*CrossfadeEditAuditionButton*" style "red_when_active" +widget "*CrossfadeEditCurveButton" style "red_when_active" +widget "*CrossfadeEditCurveButton*" style "red_when_active" +widget "*CrossfadeEditLabel" style "medium_text" +widget "*CrossfadeEditFrame" style "base_frame" +widget "*MouseModeButton" style "default_buttons_menus" +widget "*MouseModeButton*" style "default_buttons_menus" +widget "*EditorWindow" style "default_base" +widget "*EditorMainCanvas" style "main_canvas_area" +widget "*AudioTrackControlsBaseInactiveUnselected" style "track_controls_inactive" +widget "*BusControlsBaseInactiveUnselected" style "track_controls_inactive" +widget "*AutomationTrackControlsBaseInactiveUnselected" style "track_controls_inactive" +widget "*AudioTrackControlsBaseInactiveSelected" style "track_controls_inactive" +widget "*BusControlsBaseInactiveSelected" style "track_controls_inactive" +widget "*AutomationTrackControlsBaseInactiveSelected" style "track_controls_inactive" +widget "*AudioTrackStripBaseInactive" style "track_controls_inactive" +widget "*AudioBusStripBaseInactive" style "track_controls_inactive" +widget "*AudioTrackControlsBaseSelected" style "edit_controls_base_selected" +widget "*BusControlsBaseSelected" style "edit_controls_base_selected" +widget "*AutomationTrackControlsBase" style "automation_track_controls_base" +widget "*AutomationTrackControlsBaseSelected" style "edit_controls_base_selected" +widget "*EditorMenuBar*" style "black_mackie_menu_bar" +widget "*MainMenuBar*" style "black_mackie_menu_bar" +widget "*ZoomClickBox" style "medium_bold_entry" +widget "*PluginParameterLabel" style "medium_text" +widget "*PluginNameInfo" style "plugin_name_text" +widget "*PluginMakerInfo" style "plugin_maker_text" +widget "*PluginParameterInfo" style "medium_text" +widget "*MotionControllerValue" style "medium_entry" +widget "*ParameterValueDisplay" style "medium_bold_entry" +widget "*PluginUIClickBox" style "medium_bold_entry" +widget "*PluginUIClickBox*" style "medium_bold_entry" +widget "*PluginSlider" style "plugin_slider" +widget "*TrackListDisplay" style "track_list_display" +widget "*TrackListDisplay.*" style "small_bold_text" +widget "*RegionListDisplay" style "small_bold_entry" +widget "*RegionListDisplay.*" style "small_bold_text" +widget "*MixerRedirectSelector" style "small_bold_entry" +widget "*MixerRedirectSelector.*" style "small_bold_text" +widget "*MixerTrackNameArea" style "default_base" +widget "*MixerTrackCommentArea" style "option_entry" +widget "*MixerPanZone" style "pan_zone" +widget "*MixerTrackDisplayList" style "track_list_display" +widget "*MixerSnapshotDisplayList" style "track_list_display" +widget "*MixerAuxDisplayList" style "track_list_display" +widget "*MixerGroupList" style "track_list_display" +widget "*WallClock" style "wall_clock" +widget "*CPULoad" style "wall_clock" +widget "*RegionEditorLabel" style "medium_text" +widget "*RegionEditorSmallLabel" style "small_text" +widget "*RegionEditorEntry" style "medium_entry" +widget "*RegionEditorClock" style "default_clock_display" +widget "*RegionEditorToggleButton" style "paler_red_when_active" +widget "*RegionEditorToggleButton*" style "paler_red_when_active" +widget "*MixerStripSpeedBase" style "small_entry" +widget "*MixerStripSpeedBase*" style "small_entry" +widget "*MixerStripSpeedBaseNotOne" style "small_red_on_black_entry" +widget "*MixerStripSpeedBaseNotOne*" style "small_red_on_black_entry" +widget "*MixerStripGainDisplay" style "small_entry" +widget "*MixerStripGainUnitButton" style "very_small_button" +widget "*MixerStripGainUnitButton*" style "very_small_button" +widget "*MixerStripMeterPreButton" style "very_small_button" +widget "*MixerStripMeterPreButton*" style "very_small_button" +widget "*MixerStripPeakDisplay*" style "red_active_small_entry" +widget "*MixerStripPeakDisplayPeak*" style "peak_display_peaked_entry" +widget "*MixerStripSelectedFrame" style "selected_strip_frame" +widget "*MixerStripFrame" style "base_frame" +widget "*HWMonitorButton" style "red_when_active" +widget "*HWMonitorButton*" style "red_when_active" +widget "*BypassButton" style "red_when_active" +widget "*BypassButton*" style "red_when_active" +widget "*TransportSoloAlert" style "flashing_alert" +widget "*TransportSoloAlert.*" style "flashing_alert" +widget "*TransportAuditioningAlert" style "flashing_alert" +widget "*TransportAuditioningAlert.*" style "flashing_alert" +widget "*Prompter" style "default_base" +widget "*PrompterLabel" style "default_base" +widget "*CleanupDialog" style "default_base" +widget "*CleanupDialog*" style "default_base" +widget "*FadeCurve" style "medium_bold_entry" +widget "*FadeCurve*" style "medium_bold_entry" +widget "*IOSelectorButton" style "default_buttons_menus" +widget "*IOSelectorButton*" style "default_buttons_menus" +widget "*IOSelectorList" style "medium_entry_noselection_fg" +widget "*IOSelectorPortList" style "io_selector_port_list" +widget "*IOSelectorPortListSelected" style "selected_io_selector_port_list" +widget "*IOSelectorNotebook" style "io_selector_notebook" +widget "*IOSelectorNotebookTab" style "io_selector_notebook" +widget "*IOSelectorFrame" style "base_frame" +widget "*ConnectionEditorButton" style "default_buttons_menus" +widget "*ConnectionEditorButton*" style "default_buttons_menus" +widget "*ConnectionEditorList" style "medium_entry_noselection_fg" +widget "*ConnectionEditorConnectionList" style "medium_entry" +widget "*ConnectionEditorPortList" style "io_selector_port_list" +widget "*ConnectionEditorPortListSelected" style "selected_io_selector_port_list" +widget "*ConnectionEditorNotebook" style "io_selector_notebook" +widget "*ConnectionEditorNotebookTab" style "io_selector_notebook" +widget "*ConnectionEditorFrame" style "base_frame" +widget "*RouteParamsListDisplay" style "track_list_display" +widget "*RouteParamsPreListDisplay" style "track_list_display" +widget "*RouteParamsPostListDisplay" style "track_list_display" +widget "*TearOffArrow" style "tearoff_arrow" +widget "*RouteParamsTitleButton" style "medium_text" +widget "*RouteParamsTitleLabel" style "medium_text" +widget "*PluginAutomateRecordButton" style "small_red_active_and_selected_button" +widget "*PluginAutomateRecordButton*" style "small_red_active_and_selected_button" +widget "*PluginAutomatePlayButton" style "small_red_active_and_selected_button" +widget "*PluginAutomatePlayButton*" style "small_red_active_and_selected_button" +widget "*PluginAutomateButton" style "small_button" +widget "*PluginAutomateButton*" style "small_button" +widget "*PluginSaveButton" style "small_button" +widget "*PluginSaveButton*" style "small_button" +widget "*PluginLoadButton" style "small_button" +widget "*PluginLoadButton*" style "small_button" +widget "*FaderMetricsStrip" style "meter_metrics_strip" +widget "*MeterMetricsStrip" style "meter_metrics_strip" +widget "*NoSessionMessage" style "no_session_msg" +widget "*MetricDialogFrame" style "base_frame" +widget "*MetricEntry" style "medium_bold_entry" +widget "*MetricButton" style "default_buttons_menus" +widget "*MetricButton.*" style "default_buttons_menus" +widget "*MetricLabel" style "medium_text" +widget "*TimeStretchButton" style "default_buttons_menus" +widget "*TimeStretchButton.*" style "default_buttons_menus" +widget "*TimeStretchProgress" style "default_buttons_menus" +widget "*ChoiceWindow" style "default_buttons_menus" +widget "*ChoicePrompt" style "default_buttons_menus" +widget "*ChoiceButton" style "default_buttons_menus" +widget "*ChoiceButton*" style "default_buttons_menus" +widget "*SelectionModeButton" style "default_buttons_menus" +widget "*SelectionModeButton*" style "default_buttons_menus" +widget "*TrackLabel" style "medium_text" +widget "*TrackPlugName" style "medium_text" +widget "*TrackParameterName" style "small_text" +widget "*AddRouteDialog*" style "medium_text" +widget "*AddRouteDialog.GtkLabel" style "medium_text" +widget "*AddRouteDialogChannelChoice" style "medium_bold_entry" +widget "*AddRouteDialogSpinner" style "medium_bold_entry" +widget "*AddRouteDialogSpinner*" style "medium_bold_entry" +widget "*AddRouteDialogRadioButton" style "red_when_active" +widget "*AddRouteDialogButton" style "default_buttons_menus" +widget "*AddRouteDialogNameTemplateEntry" style "medium_bold_entry" +widget "*NewSessionIOLabel" style "larger_bold_text" +widget "*NewSessionSR1Label" style "red_medium_text" +widget "*NewSessionSR2Label" style "medium_text" +widget "*NewSessionChannelChoice" style "medium_bold_entry" +widget "*NewSessionMainButton" style "larger_bold_text" +widget "*NewSessionMainButton*" style "larger_bold_text" +widget "*NewSessionMainLabel" style "larger_bold_text" +widget "*LocationEditRowClock" style "location_rows_clock" +widget "*LocationEditNameLabel" style "medium_text" +widget "*LocationEditSetButton" style "location_row_button" +widget "*LocationEditSetButton*" style "location_row_button" +widget "*LocationEditGoButton" style "location_row_button" +widget "*LocationEditGoButton*" style "location_row_button" +widget "*LocationEditCdButton" style "small_red_active_and_selected_button" +widget "*LocationEditCdButton*" style "small_red_active_and_selected_button" +widget "*LocationEditHideButton" style "small_red_active_and_selected_button" +widget "*LocationEditHideButton*" style "small_red_active_and_selected_button" +widget "*LocationEditNumberLabel" style "small_text" +widget "*LocationLocEditorFrame" style "base_frame" +widget "*LocationRangeEditorFrame" style "base_frame" +widget "*LocationEditNameEntry" style "option_entry" +widget "*LocationAddLocationButton" style "default_buttons_menus" +widget "*LocationAddLocationButton*" style "default_buttons_menus" +widget "*LocationAddRangeButton" style "default_buttons_menus" +widget "*LocationAddRangeButton*" style "default_buttons_menus" +widget "*LocationEditRemoveButton" style "location_row_button" +widget "*LocationEditRemoveButton*" style "location_row_button" +widget "*PanSlider" style "pan_slider" +widget "*PanningLinkButton" style "mixer_red_active_button" +widget "*PanningLinkButton.*" style "mixer_red_active_button" +widget "*PanningLinkDirectionButton" style "very_small_button" +widget "*PanningLinkDirectionButton.*" style "very_small_button" +widget "*ChannelCountSelector" style "medium_bold_entry" +widget "*ChannelCountSelector.GtkArrow" style "default_buttons_menus" + +class "GtkWidget" style "default_base" +class "GtkScrollbar" style "ardour_adjusters" +class "GtkLabel" style "default_buttons_menus" +class "GtkButton" style "default_buttons_menus" +class "GtkArrow" style "tearoff_arrow" +class "GtkProgressBar" style "ardour_progressbars" + + +# +#---------------------------------------------------------------------- +# +# Below this point, all styles refer to colors used by canvas items +# not actual widgets. The "red" value of the active state is used +# to define the "alpha" value for the RGBA value. Other color values +# for the active state are ignored. +# + +style "cWaveForm" +{ + fg[NORMAL] = { 0.0, 0.0, 0.0 } + fg[ACTIVE] = { 0.80, 0, 0 } +} +widget "*cWaveForm" style "cWaveForm" + +style "cMutedWaveForm" +{ + fg[NORMAL] = { 0.35, 0.35, 0.35 } + #fg[NORMAL] = { 0.80, 0.80, 0.70 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cMutedWaveForm" style "cMutedWaveForm" + +style "cSelectedFrameBase" +{ + fg[NORMAL] = { 0.71, 0.57, 0.66 } + #fg[NORMAL] = { 0.10, 0.10, 0.10 } + fg[ACTIVE] = { 1.0, 0, 0 } # Not used, opacity set by region editor +} +widget "*cSelectedFrameBase" style "cSelectedFrameBase" + +style "cFrameBase" +{ + fg[NORMAL] = { 0.75, 0.75, 0.76 } + fg[ACTIVE] = { 1.0, 0, 0 } # Not used, opacity set by region editor +} +widget "*cFrameBase" style "cFrameBase" + +style "cAudioTrackBase" +{ + fg[NORMAL] = { 0.79, 0.80, 0.85 } + #fg[NORMAL] = { 0, 0, 0 } + fg[ACTIVE] = { 0.41, 0, 0 } + #fg[ACTIVE] = { 0.70, 0, 0 } +} +widget "*cAudioTrackBase" style "cAudioTrackBase" + +style "cAudioTrackOutline" +{ + fg[NORMAL] = { 0.00, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cAudioTrackOutline" style "cAudioTrackOutline" + +style "cAudioBusBase" +{ + fg[NORMAL] = { 0.90, 0.82, 0.90 } + fg[ACTIVE] = { 0.41, 0, 0 } +} +widget "*cAudioBusBase" style "cAudioBusBase" + +style "cTempoBar" +{ + fg[NORMAL] = { 0.64, 0.64, 0.62 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*TempoBar" style "cTempoBar" + +style "cMeterBar" +{ + fg[NORMAL] = { 0.75, 0.75, 0.73 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cMeterBar" style "cMeterBar" + +style "cMarkerBar" +{ + fg[NORMAL] = { 0.54, 0.54, 0.52 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cMarkerBar" style "cMarkerBar" + +style "cRangeMarkerBar" +{ + fg[NORMAL] = { 0.48, 0.48, 0.46 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cRangeMarkerBar" style "cRangeMarkerBar" + +style "cTransportMarkerBar" +{ + fg[NORMAL] = { 0.40, 0.40, 0.38 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cTransportMarkerBar" style "cTransportMarkerBar" + +style "cTimeStretchFill" +{ + fg[NORMAL] = { 0.89, 0.71, 0.71 } + fg[ACTIVE] = { 0.59, 0, 0 } +} +widget "*cTimeStretchFill" style "cTimeStretchFill" + +style "cTimeStretchOutline" +{ + fg[NORMAL] = { 0.39, 0.39, 0.39 } + fg[ACTIVE] = { 0.59, 0, 0 } +} +widget "*cTimeStretchOutline" style "cTimeStretchOutline" + +style "cAutomationLine" +{ + fg[NORMAL] = { 0.27, 0.74, 0.35 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cAutomationLine" style "cAutomationLine" + +style "cLeftPanAutomationLine" +{ + fg[NORMAL] = { 0.77, 0.24, 0.01 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cLeftPanAutomationLine" style "cLeftPanAutomationLine" + +style "cRightPanAutomationLine" +{ + fg[NORMAL] = { 0.03, 0.26, 0.73 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cRightPanAutomationLine" style "cRightPanAutomationLine" + +style "cRedirectAutomationLine" +{ + fg[NORMAL] = { 0.28, 0.34, 0.74 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cRedirectAutomationLine" style "cRedirectAutomationLine" + +style "cControlPointFill" +{ + fg[NORMAL] = { 0, 0, 0 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cControlPointFill" style "cControlPointFill" + +style "cControlPointOutline" +{ + fg[NORMAL] = { 0, 0, 0 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cControlPointOutline" style "cControlPointOutline" + +style "cEnteredControlPointOutline" +{ + fg[NORMAL] = { 1.0, 0.21, 0.21 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cEnteredControlPointOutline" style "cEnteredControlPointOutline" + +style "cEnteredControlPointSelected" +{ + fg[NORMAL] = { 0.00, 1.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cEnteredControlPointSelected" style "cEnteredControlPointSelected" + +style "cEnteredControlPoint" +{ + fg[NORMAL] = { 1.00, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cEnteredControlPoint" style "cEnteredControlPoint" + +style "cControlPointSelected" +{ + fg[NORMAL] = { 0.91, 0.04, 0.04 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cControlPointSelected" style "cControlPointSelected" + +style "cControlPoint" +{ + fg[NORMAL] = { 0.00, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cControlPoint" style "cControlPoint" + +style "cAutomationTrackFill" +{ + fg[NORMAL] = { 0.63, 0.63, 0.81 } + fg[ACTIVE] = { 0.41, 0, 0 } +} +widget "*cAutomationTrackFill" style "cAutomationTrackFill" + +style "cAutomationTrackOutline" +{ + fg[NORMAL] = { 0.16, 0.16, 0.16 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cAutomationTrackOutline" style "cAutomationTrackOutline" + +style "cCrossfadeEditorBase" +{ + fg[NORMAL] = { 0.16, 0.18, 0.29 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cCrossfadeEditorBase" style "cCrossfadeEditorBase" + +style "cCrossfadeEditorLine" +{ + fg[NORMAL] = { 1.0, 0.86, 0.86 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cCrossfadeEditorLine" style "cCrossfadeEditorLine" + +style "cSelectedCrossfadeEditorLine" +{ + fg[NORMAL] = { 0, 0.86, 0.86 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cSelectedCrossfadeEditorLine" style "cSelectedCrossfadeEditorLine" + +style "cCrossfadeEditorLineShading" +{ + fg[NORMAL] = { 0, 0.63, 0.82 } + fg[ACTIVE] = { 0.33, 0, 0 } +} +widget "*cCrossfadeEditorLineShading" style "cCrossfadeEditorLineShading" + +style "cCrossfadeEditorPointFill" +{ + fg[NORMAL] = { 0, 1.0, 0 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cCrossfadeEditorPointFill" style "cCrossfadeEditorPointFill" + +style "cCrossfadeEditorPointOutline" +{ + fg[NORMAL] = { 0, 0, 1.0 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cCrossfadeEditorPointOutline" style "cCrossfadeEditorPointOutline" + +style "cCrossfadeEditorWave" +{ + fg[NORMAL] = { 1.0, 1.0, 1.0 } + fg[ACTIVE] = { 0.36, 0, 0 } +} +widget "*cCrossfadeEditorWave" style "cCrossfadeEditorWave" + +style "cSelectedCrossfadeEditorWave" +{ + fg[NORMAL] = { 0.98, 0.92, 0.08 } + fg[ACTIVE] = { 0.63, 0, 0 } +} +widget "*cSelectedCrossfadeEditorWave" style "cSelectedCrossfadeEditorWave" + +style "cCrossfadeLine" +{ + fg[NORMAL] = { 0, 0, 0 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cCrossfadeLine" style "cCrossfadeLine" + +style "cActiveCrossfade" +{ + fg[NORMAL] = { 0.91, 0.93, 0.24 } + fg[ACTIVE] = { 0.47, 0, 0 } +} +widget "*cActiveCrossfade" style "cActiveCrossfade" + +style "cInactiveCrossfade" +{ + fg[NORMAL] = { 1.0, 1.0, 1.0 } + fg[ACTIVE] = { 0.1, 0, 0 } +} +widget "*cInactiveCrossfade" style "cInactiveCrossfade" + +style "cLocationMarker" +{ + fg[NORMAL] = { 0.77, 0.96, 0.07 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cLocationMarker" style "cLocationMarker" + +style "cLocationRange" +{ + fg[NORMAL] = { 0.29, 0.48, 0.35 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cLocationRange" style "cLocationRange" + +style "cLocationCDMarker" +{ + fg[NORMAL] = { 0.12, 0.91, 0.77 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cLocationCDMarker" style "cLocationCDMarker" + +style "cLocationLoop" +{ + fg[NORMAL] = { 0.21, 0.59, 0.31 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cLocationLoop" style "cLocationLoop" + +style "cLocationPunch" +{ + fg[NORMAL] = { 0.49, 0.23, 0.23 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cLocationPunch" style "cLocationPunch" + +style "cVerboseCanvasCursor" +{ + fg[NORMAL] = { 0, 0, 0 } + fg[ACTIVE] = {0.74, 0, 0 } +} +widget "*cVerboseCanvasCursor" style "cVerboseCanvasCursor" + +style "cRangeDragBarRect" +{ + fg[NORMAL] = { 0.59, 0.59, 0.59 } + fg[ACTIVE] = { 0.78, 0, 0 } +} +widget "*cRangeDragBarRect" style "cRangeDragBarRect" + +style "cRangeDragBarRectFill" +{ + fg[NORMAL] = { 0.78, 0.82, 0.70 } + fg[ACTIVE] = { 0.43, 0, 0 } +} +widget "*cRangeDragBarRectFill" style "cRangeDragBarRectFill" + +style "cRangeDragRect" +{ + fg[NORMAL] = { 0.59, 0.59, 0.59 } + fg[ACTIVE] = { 0.78, 0, 0 } +} +widget "*cRangeDragRect" style "cRangeDragRect" + +style "cRangeDragRectFill" +{ + fg[NORMAL] = { 0.51, 0.78, 0.59 } + fg[ACTIVE] = { 0.78, 0, 0 } +} +widget "*cRangeDragRectFill" style "cRangeDragRectFill" + +style "cTransportDragRect" +{ + fg[NORMAL] = { 0.59, 0.59, 0.59 } + fg[ACTIVE] = { 0.78, 0, 0 } +} +widget "*cTransportDragRect" style "cTransportDragRect" + +style "cTransportDragRectFill" +{ + fg[NORMAL] = { 0.78, 0.78, 0.78 } + fg[ACTIVE] = { 1.43, 0, 0 } +} +widget "*cTransportDragRectFill" style "cTransportDragRectFill" + +style "cMarkerDragLine" +{ + fg[NORMAL] = { 0, 0.31, 0 } + fg[ACTIVE] = { 0.98, 0, 0 } +} +widget "*cMarkerDragLine" style "cMarkerDragLine" + +style "cTransportLoopRect" +{ + fg[NORMAL] = { 0.12, 0.47, 0.16 } + fg[ACTIVE] = { 0.98, 0, 0 } +} +widget "*cTransportLoopRect" style "cTransportLoopRect" + +style "cTransportLoopRectFill" +{ + fg[NORMAL] = { 0.12, 0.47, 0.16 } + fg[ACTIVE] = { 0.98, 0, 0 } +} +widget "*cTransportLoopRectFill" style "cTransportLoopRectFill" + +style "cTransportPunchRect" +{ + fg[NORMAL] = { 0.43, 0.16, 0.16 } + fg[ACTIVE] = { 0.90, 0, 0 } +} +widget "*cTransportPunchRect" style "cTransportPunchRect" + +style "cTransportPunchRectFill" +{ + fg[NORMAL] = { 0.43, 0.16, 0.16 } + fg[ACTIVE] = { 0.90, 0, 0 } +} +widget "*cTransportPunchRectFill" style "cTransportPunchRectFill" + +style "cPunchInLine" +{ + fg[NORMAL] = { 0.66, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cPunchInLine" style "cPunchInLine" + +style "cPunchOutLine" +{ + fg[NORMAL] = { 0.66, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cPunchOutLine" style "cPunchOutLine" + +style "cZoomRect" +{ + fg[NORMAL] = { 0.59, 0.59, 0.59 } + fg[ACTIVE] = { 0.78, 0, 0 } +} +widget "*cZoomRect" style "cZoomRect" + +style "cZoomRectFill" +{ + fg[NORMAL] = { 0.78, 0.82, 0.70 } + fg[ACTIVE] = { 0.43, 0, 0 } +} +widget "*cZoomRectFill" style "cZoomRectFill" + +style "cRubberBandRect" +{ + fg[NORMAL] = { 0.08, 1.00, 0.52 } + fg[ACTIVE] = { 0.59, 0, 0 } +} +widget "*cRubberBandRect" style "cRubberBandRect" + +style "cRubberBandRectFill" +{ + fg[NORMAL] = { 0.78, 0.78, 0.78 } + fg[ACTIVE] = { 0.35, 0, 0 } +} +widget "*cRubberBandRectFill" style "cRubberBandRectFill" + +style "cFirstActionMessage" +{ + fg[NORMAL] = { 0.00, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cFirstActionMessage" style "cFirstActionMessage" + +style "cEnteredGainLine" +{ + fg[NORMAL] = { 0.87, 0.39, 0.39 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cEnteredGainLine" style "cEnteredGainLine" + +style "cEnteredAutomationLine" +{ + fg[NORMAL] = { 0.87, 0.39, 0.39 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cEnteredAutomationLine" style "cEnteredAutomationLine" + +style "cEnteredMarker" +{ + fg[NORMAL] = { 0.87, 0.39, 0.39 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cEnteredMarker" style "cEnteredMarker" + +style "cMeterMarker" +{ + fg[NORMAL] = { 0.95, 0.26, 0.36 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cMeterMarker" style "cMeterMarker" + +style "cTempoMarker" +{ + fg[NORMAL] = { 0.95, 0.26, 0.36 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cTempoMarker" style "cTempoMarker" + +style "cMeasureLineBeat" +{ + fg[NORMAL] = { 0.80, 0.59, 0.51 } + fg[ACTIVE] = { 0.98, 0, 0 } +} +widget "*cMeasureLineBeat" style "cMeasureLineBeat" + +style "cMeasureLineBar" +{ + fg[NORMAL] = { 0.68, 1.0, 0.59 } + fg[ACTIVE] = { 0.94, 0, 0 } +} +widget "*cMeasureLineBar" style "cMeasureLineBar" + +style "cGhostTrackBaseOutline" +{ + fg[NORMAL] = { 0.00, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cGhostTrackBaseOutline" style "cGhostTrackBaseOutline" + +style "cGhostTrackBaseFill" +{ + fg[NORMAL] = { 0.27, 0.00, 0.49 } + fg[ACTIVE] = { 0.50, 0, 0 } +} +widget "*cGhostTrackBaseFill" style "cGhostTrackBaseFill" + +style "cGhostTrackWave" +{ + fg[NORMAL] = { 1.0, 0.00, 0.00 } + fg[ACTIVE] = { 0.50, 0, 0 } +} +widget "*cGhostTrackWave" style "cGhostTrackWave" + +style "cImageTrackBase" +{ + fg[NORMAL] = { 0.87, 0.87, 0.85 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cImageTrackBase" style "cImageTrackBase" + +style "cImageTrackOutline" +{ + fg[NORMAL] = { 0.00, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cImageTrackOutline" style "cImageTrackOutline" + +style "cMarkerTrackBase" +{ + fg[NORMAL] = { 0.87, 0.87, 0.85 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cMarkerTrackBase" style "cMarkerTrackBase" + +style "cMarkerTrackOutline" +{ + fg[NORMAL] = { 0.00, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cMarkerTrackOutline" style "cMarkerTrackOutline" + +style "cZeroLine" +{ + fg[NORMAL] = { 0.71, 0.71, 0.71 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cZeroLine" style "cZeroLine" + +style "cGainLine" +{ + fg[NORMAL] = { 0.00, 1.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cGainLine" style "cGainLine" + +style "cGainLineInactive" +{ + fg[NORMAL] = { 0.06, 0.06, 0.06 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cGainLineInactive" style "cGainLineInactive" + +style "cRecordingRectFill" +{ + fg[NORMAL] = { 0.90, 0.78, 0.78 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cRecordingRectFill" style "cRecordingRectFill" + +style "cRecordingRectOutline" +{ + fg[NORMAL] = { 0.31, 0.16, 0.16 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cRecordingRectOutline" style "cRecordingRectOutline" + +style "cSelectionRectFill" +{ + fg[NORMAL] = { 0.91, 0.96, 0.83 } + fg[ACTIVE] = { 0.47, 0, 0 } +} +widget "*cSelectionRectFill" style "cSelectionRectFill" + +style "cSelectionRectOutline" +{ + fg[NORMAL] = { 0.39, 0.39, 0.39 } + fg[ACTIVE] = { 0.59, 0, 0 } +} +widget "*cSelectionRectOutline" style "cSelectionRectOutline" + +style "cSelectionEndFill" +{ + fg[NORMAL] = { 0.39, 0.39, 0.39 } + fg[ACTIVE] = { 0.70, 0, 0 } +} +widget "*cSelectionEndFill" style "cSelectionEndFill" + +style "cSelectionEndOutline" +{ + fg[NORMAL] = { 0.39, 0.39, 0.39 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cSelectionEndOutline" style "cSelectionEndOutline" + +style "cSelectionStartFill" +{ + fg[NORMAL] = { 0.39, 0.39, 0.39 } + fg[ACTIVE] = { 0.70, 0, 0 } +} +widget "*cSelectionStartFill" style "cSelectionStartFill" + +style "cSelectionStartOutline" +{ + fg[NORMAL] = { 0.39, 0.39, 0.39 } + fg[ACTIVE] = { 1.0, 0, 0 } +} +widget "*cSelectionStartOutline" style "cSelectionStartOutline" + +style "cVestigialFrameFill" +{ + fg[NORMAL] = { 0.27, 0.00, 0.49 } + fg[ACTIVE] = { 0.06, 0, 0 } +} +widget "*cVestigialFrameFill" style "cVestigialFrameFill" + +style "cVestigialFrameOutline" +{ + fg[NORMAL] = { 0.00, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cVestigialFrameOutline" style "cVestigialFrameOutline" + +style "cTimeAxisFrameFill" +{ + fg[NORMAL] = { 0.27, 0.00, 0.49 } + fg[ACTIVE] = { 0.06, 0, 0 } +} +widget "*cTimeAxisFrameFill" style "cTimeAxisFrameFill" + +style "cTimeAxisFrameOutline" +{ + fg[NORMAL] = { 0.00, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cTimeAxisFrameOutline" style "cTimeAxisFrameOutline" + +style "cNameHighlightFill" +{ + fg[NORMAL] = { 0.00, 0.00, 1.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cNameHighlightFill" style "cNameHighlightFill" + +style "cNameHighlightOutline" +{ + fg[NORMAL] = { 0.49, 0.00, 1.00 } + fg[ACTIVE] = { 0.59, 0, 0 } +} +widget "*cNameHighlightOutline" style "cNameHighlightOutline" + +style "cFrameHandleStartFill" +{ + fg[NORMAL] = { 0.49, 0.00, 1.00 } + fg[ACTIVE] = { 0.59, 0, 0 } +} +widget "*cFrameHandleStartFill" style "cFrameHandleStartFill" + +style "cFrameHandleStartOutline" +{ + fg[NORMAL] = { 0.00, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cFrameHandleStartOutline" style "cFrameHandleStartOutline" + +style "cFrameHandleEndFill" +{ + fg[NORMAL] = { 0.49, 0.00, 1.00 } + fg[ACTIVE] = { 0.59, 0, 0 } +} +widget "*cFrameHandleEndFill" style "cFrameHandleEndFill" + +style "cFrameHandleEndOutline" +{ + fg[NORMAL] = { 0.00, 0.00, 0.00 } + fg[ACTIVE] = { 1.00, 0, 0 } +} +widget "*cFrameHandleEndOutline" style "cFrameHandleEndOutline" + +style "cTrimHandleLockedStart" +{ + fg[NORMAL] = { 0.92, 0.06, 0.06 } + fg[ACTIVE] = { 0.16, 0, 0 } +} +widget "*cTrimHandleLockedStart" style "cTrimHandleLockedStart" + +style "cTrimHandleLockedEnd" +{ + fg[NORMAL] = { 0.92, 0.06, 0.06 } + fg[ACTIVE] = { 0.16, 0, 0 } +} +widget "*cTrimHandleLockedEnd" style "cTrimHandleLockedEnd" + +style "cTrimHandleStart" +{ + fg[NORMAL] = { 0.10, 0.00, 1.00 } + fg[ACTIVE] = { 0.27, 0, 0 } +} +widget "*cTrimHandleStart" style "cTrimHandleStart" + +style "cTrimHandleEnd" +{ + fg[NORMAL] = { 0.10, 0.00, 1.00 } + fg[ACTIVE] = { 0.27, 0, 0 } +} +widget "*cTrimHandleEnd" style "cTrimHandleEnd" diff --git a/gtk2_ardour/ardour_ui2.cc b/gtk2_ardour/ardour_ui2.cc new file mode 100644 index 0000000000..808e306e81 --- /dev/null +++ b/gtk2_ardour/ardour_ui2.cc @@ -0,0 +1,785 @@ +/* + Copyright (C) 1999 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ardour_ui.h" +#include "public_editor.h" +#include "audio_clock.h" +#include "extra_bind.h" + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; +using namespace Gtkmmext; +using namespace Gtk; +using namespace SigC; + +int +ARDOUR_UI::setup_windows () +{ + using namespace Menu_Helpers; + + if (create_editor ()) { + error << _("UI: cannot setup editor") << endmsg; + return -1; + } + + if (create_mixer ()) { + error << _("UI: cannot setup mixer") << endmsg; + return -1; + } + + if (create_meter_bridge ()) { + error << _("UI: cannot setup meter_bridge") << endmsg; + return -1; + } + + /* all other dialogs are created conditionally */ + + we_have_dependents (); + + setup_clock (); + setup_transport(); + setup_adjustables (); + build_menu_bar (); + + top_packer.pack_start (menu_bar_base, false, false); + top_packer.pack_start (transport_frame, false, false); + + editor->add_toplevel_controls (top_packer); + + return 0; +} + + +void +ARDOUR_UI::setup_adjustables () + +{ + adjuster_table.set_homogeneous (true); + + online_control_strings.push_back (_("MMC + Local")); + online_control_strings.push_back (_("MMC")); + online_control_strings.push_back (_("Local")); + + online_control_button = new GlobalClickBox ("CONTROL", + online_control_strings); + + online_control_button->adjustment.value_changed.connect(slot (*this,&ARDOUR_UI::control_methods_adjusted)); + + mmc_id_strings.push_back ("1"); + mmc_id_strings.push_back ("2"); + mmc_id_strings.push_back ("3"); + mmc_id_strings.push_back ("4"); + mmc_id_strings.push_back ("5"); + mmc_id_strings.push_back ("6"); + mmc_id_strings.push_back ("7"); + mmc_id_strings.push_back ("8"); + mmc_id_strings.push_back ("9"); + + mmc_id_button = new GlobalClickBox (_("MMC ID"), mmc_id_strings); + + mmc_id_button->adjustment.value_changed.connect (slot (*this,&ARDOUR_UI::mmc_device_id_adjusted)); + + adjuster_table.attach (*online_control_button, 0, 2, 1, 2, GTK_FILL|GTK_EXPAND, 0, 5, 5); + adjuster_table.attach (*mmc_id_button, 2, 3, 1, 2, 0, 0, 5, 5); +} + +#include "transport_xpms" + +void +ARDOUR_UI::transport_stopped () +{ + roll_button.set_active (false); + play_selection_button.set_active (false); + auto_loop_button.set_active (false); + + shuttle_fract = 0; + shuttle_box.queue_draw (); + + update_disk_space (); +} + +static const double SHUTTLE_FRACT_SPEED1=0.48412291827; /* derived from A1,A2 */ + +void +ARDOUR_UI::transport_rolling () +{ + if (session->get_play_range()) { + + play_selection_button.set_active (true); + roll_button.set_active (false); + auto_loop_button.set_active (false); + + } else if (session->get_auto_loop ()) { + + auto_loop_button.set_active (true); + play_selection_button.set_active (false); + roll_button.set_active (false); + + } else { + + roll_button.set_active (true); + play_selection_button.set_active (false); + auto_loop_button.set_active (false); + } + + /* reset shuttle controller */ + + shuttle_fract = SHUTTLE_FRACT_SPEED1; /* speed = 1.0, believe it or not */ + shuttle_box.queue_draw (); +} + +void +ARDOUR_UI::transport_rewinding () +{ + roll_button.set_active (true); + play_selection_button.set_active (false); + auto_loop_button.set_active (false); +} + +void +ARDOUR_UI::transport_forwarding () +{ + roll_button.set_active (true); + play_selection_button.set_active (false); + auto_loop_button.set_active (false); +} + +void +ARDOUR_UI::setup_transport () +{ + transport_tearoff = manage (new TearOff (transport_tearoff_hbox)); + transport_tearoff->set_name ("TransportBase"); + + transport_hbox.pack_start (*transport_tearoff, true, false); + + transport_base.set_name ("TransportBase"); + transport_base.add (transport_hbox); + + transport_frame.set_shadow_type (GTK_SHADOW_OUT); + transport_frame.set_name ("BaseFrame"); + transport_frame.add (transport_base); + + transport_tearoff->Detach.connect (bind (slot (*this, &ARDOUR_UI::detach_tearoff), static_cast(&top_packer), + static_cast(&transport_frame))); + transport_tearoff->Attach.connect (bind (slot (*this, &ARDOUR_UI::reattach_tearoff), static_cast (&top_packer), + static_cast (&transport_frame), 1)); + + + goto_start_button.add (*(manage (new Gtk::Pixmap (start_xpm)))); + goto_end_button.add (*(manage (new Gtk::Pixmap (end_xpm)))); + roll_button.add (*(manage (new Gtk::Pixmap (arrow_xpm)))); + stop_button.add (*(manage (new Gtk::Pixmap (stop_xpm)))); + play_selection_button.add (*(manage (new Gtk::Pixmap (play_selection_xpm)))); + rec_button.add (*(manage (new Gtk::Pixmap (rec_xpm)))); + auto_loop_button.add (*(manage (new Gtk::Pixmap (loop_xpm)))); + + ARDOUR_UI::instance()->tooltips().set_tip (roll_button, _("Play from playhead")); + ARDOUR_UI::instance()->tooltips().set_tip (stop_button, _("Stop playback")); + ARDOUR_UI::instance()->tooltips().set_tip (play_selection_button, _("Play range/selection")); + ARDOUR_UI::instance()->tooltips().set_tip (goto_start_button, _("Go to start of session")); + ARDOUR_UI::instance()->tooltips().set_tip (goto_end_button, _("Go to end of session")); + ARDOUR_UI::instance()->tooltips().set_tip (auto_loop_button, _("Play loop range")); + ARDOUR_UI::instance()->tooltips().set_tip (auto_return_button, _("Return to last playback start when stopped")); + ARDOUR_UI::instance()->tooltips().set_tip (auto_play_button, _("Start playback after any locate")); + ARDOUR_UI::instance()->tooltips().set_tip (auto_input_button, _("Be sensible about input monitoring")); + ARDOUR_UI::instance()->tooltips().set_tip (punch_in_button, _("Start recording at auto-punch start")); + ARDOUR_UI::instance()->tooltips().set_tip (punch_out_button, _("Stop recording at auto-punch end")); + ARDOUR_UI::instance()->tooltips().set_tip (click_button, _("Enable/Disable audio click")); + ARDOUR_UI::instance()->tooltips().set_tip (follow_button, _("Enable/Disable follow playhead")); + ARDOUR_UI::instance()->tooltips().set_tip (shuttle_box, _("Shuttle speed control")); + ARDOUR_UI::instance()->tooltips().set_tip (shuttle_units_button, _("Select semitones or %%-age for speed display")); + ARDOUR_UI::instance()->tooltips().set_tip (shuttle_style_button, _("Select sprung or wheel behaviour")); + ARDOUR_UI::instance()->tooltips().set_tip (speed_display_box, _("Current transport speed")); + + shuttle_box.set_flags (GTK_CAN_FOCUS); + shuttle_box.set_events (shuttle_box.get_events() | GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK|GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_PRESS_MASK|GDK_POINTER_MOTION_MASK); + shuttle_box.set_usize (100, 15); + + shuttle_box.set_name ("TransportButton"); + goto_start_button.set_name ("TransportButton"); + goto_end_button.set_name ("TransportButton"); + roll_button.set_name ("TransportButton"); + stop_button.set_name ("TransportButton"); + play_selection_button.set_name ("TransportButton"); + rec_button.set_name ("TransportRecButton"); + auto_loop_button.set_name ("TransportButton"); + auto_return_button.set_name ("TransportButton"); + auto_play_button.set_name ("TransportButton"); + auto_input_button.set_name ("TransportButton"); + punch_in_button.set_name ("TransportButton"); + punch_out_button.set_name ("TransportButton"); + click_button.set_name ("TransportButton"); + follow_button.set_name ("TransportButton"); + + goto_start_button.unset_flags (GTK_CAN_FOCUS); + goto_end_button.unset_flags (GTK_CAN_FOCUS); + roll_button.unset_flags (GTK_CAN_FOCUS); + stop_button.unset_flags (GTK_CAN_FOCUS); + play_selection_button.unset_flags (GTK_CAN_FOCUS); + rec_button.unset_flags (GTK_CAN_FOCUS); + auto_loop_button.unset_flags (GTK_CAN_FOCUS); + auto_return_button.unset_flags (GTK_CAN_FOCUS); + auto_play_button.unset_flags (GTK_CAN_FOCUS); + auto_input_button.unset_flags (GTK_CAN_FOCUS); + punch_out_button.unset_flags (GTK_CAN_FOCUS); + punch_in_button.unset_flags (GTK_CAN_FOCUS); + click_button.unset_flags (GTK_CAN_FOCUS); + follow_button.unset_flags (GTK_CAN_FOCUS); + + goto_start_button.set_events (goto_start_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + goto_end_button.set_events (goto_end_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + roll_button.set_events (roll_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + stop_button.set_events (stop_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + play_selection_button.set_events (play_selection_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + rec_button.set_events (rec_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + auto_loop_button.set_events (auto_loop_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + auto_return_button.set_events (auto_return_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + auto_play_button.set_events (auto_play_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + auto_input_button.set_events (auto_input_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + click_button.set_events (click_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + follow_button.set_events (click_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + punch_in_button.set_events (punch_in_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + punch_out_button.set_events (punch_out_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + + goto_start_button.clicked.connect (slot (*this,&ARDOUR_UI::transport_goto_start)); + goto_end_button.clicked.connect (slot (*this,&ARDOUR_UI::transport_goto_end)); + + roll_button.button_release_event.connect (slot (*this,&ARDOUR_UI::mouse_transport_roll)); + play_selection_button.button_release_event.connect (slot (*this,&ARDOUR_UI::mouse_transport_play_selection)); + auto_loop_button.button_release_event.connect (slot (*this,&ARDOUR_UI::mouse_transport_loop)); + + stop_button.button_release_event.connect (slot (*this,&ARDOUR_UI::mouse_transport_stop)); + rec_button.button_release_event.connect (slot (*this,&ARDOUR_UI::mouse_transport_record)); + + shuttle_box.button_press_event.connect (slot (*this, &ARDOUR_UI::shuttle_box_button_press)); + shuttle_box.button_release_event.connect (slot (*this, &ARDOUR_UI::shuttle_box_button_release)); + shuttle_box.motion_notify_event.connect (slot (*this, &ARDOUR_UI::shuttle_box_motion)); + shuttle_box.expose_event.connect (slot (*this, &ARDOUR_UI::shuttle_box_expose)); + + /* clocks, etc. */ + + ARDOUR_UI::Clock.connect (bind (slot (primary_clock, &AudioClock::set), false)); + ARDOUR_UI::Clock.connect (bind (slot (secondary_clock, &AudioClock::set), false)); + + primary_clock.set_mode (AudioClock::SMPTE); + primary_clock.set_name ("TransportClockDisplay"); + secondary_clock.set_mode (AudioClock::BBT); + secondary_clock.set_name ("TransportClockDisplay"); + + + primary_clock.ValueChanged.connect (slot (*this, &ARDOUR_UI::primary_clock_value_changed)); + secondary_clock.ValueChanged.connect (slot (*this, &ARDOUR_UI::secondary_clock_value_changed)); + + ARDOUR_UI::instance()->tooltips().set_tip (primary_clock, _("Primary clock")); + ARDOUR_UI::instance()->tooltips().set_tip (secondary_clock, _("secondary clock")); + + /* options */ + + auto_return_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_auto_return)); + auto_play_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_auto_play)); + auto_input_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_auto_input)); + click_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_click)); + follow_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_follow)); + punch_in_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_punch_in)); + punch_out_button.toggled.connect (slot (*this,&ARDOUR_UI::toggle_punch_out)); + + preroll_button.unset_flags (GTK_CAN_FOCUS); + preroll_button.set_events (preroll_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + preroll_button.set_name ("TransportButton"); + + postroll_button.unset_flags (GTK_CAN_FOCUS); + postroll_button.set_events (postroll_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + postroll_button.set_name ("TransportButton"); + + preroll_clock.set_mode (AudioClock::MinSec); + preroll_clock.set_name ("TransportClockDisplay"); + postroll_clock.set_mode (AudioClock::MinSec); + postroll_clock.set_name ("TransportClockDisplay"); + + /* alerts */ + + /* CANNOT bind these to clicked or toggled, must use pressed or released */ + + solo_alert_button.set_name ("TransportSoloAlert"); + solo_alert_button.pressed.connect (slot (*this,&ARDOUR_UI::solo_alert_toggle)); + auditioning_alert_button.set_name ("TransportAuditioningAlert"); + auditioning_alert_button.pressed.connect (slot (*this,&ARDOUR_UI::audition_alert_toggle)); + + alert_box.pack_start (solo_alert_button); + alert_box.pack_start (auditioning_alert_button); + + transport_tearoff_hbox.set_border_width (5); + + transport_tearoff_hbox.pack_start (goto_start_button, false, false); + transport_tearoff_hbox.pack_start (goto_end_button, false, false); + + Gtk::Frame* sframe = manage (new Frame); + Gtk::VBox* svbox = manage (new VBox); + Gtk::HBox* shbox = manage (new HBox); + + sframe->set_shadow_type (GTK_SHADOW_IN); + sframe->add (shuttle_box); + + shuttle_box.set_name (X_("ShuttleControl")); + + speed_display_box.add (speed_display_label); + set_usize_to_display_given_text (speed_display_box, _("stopped"), 2, 2); + speed_display_box.set_name (X_("ShuttleDisplay")); + + shuttle_units_button.set_name (X_("ShuttleButton")); + shuttle_units_button.clicked.connect (slot (*this, &ARDOUR_UI::shuttle_unit_clicked)); + + shuttle_style_button.set_name (X_("ShuttleButton")); + shuttle_style_button.clicked.connect (slot (*this, &ARDOUR_UI::shuttle_style_clicked)); + + Gtk::Frame* sdframe = manage (new Frame); + + sdframe->set_shadow_type (GTK_SHADOW_IN); + sdframe->add (speed_display_box); + + shbox->pack_start (*sdframe, false, false); + shbox->pack_start (shuttle_units_button, true, true); + shbox->pack_start (shuttle_style_button, false, false); + + svbox->pack_start (*sframe, false, false); + svbox->pack_start (*shbox, false, false); + + transport_tearoff_hbox.pack_start (*svbox, false, false, 5); + + transport_tearoff_hbox.pack_start (auto_loop_button, false, false); + transport_tearoff_hbox.pack_start (play_selection_button, false, false); + transport_tearoff_hbox.pack_start (roll_button, false, false); + transport_tearoff_hbox.pack_start (stop_button, false, false); + transport_tearoff_hbox.pack_start (rec_button, false, false, 10); + + transport_tearoff_hbox.pack_start (primary_clock, false, false, 5); + transport_tearoff_hbox.pack_start (secondary_clock, false, false, 5); + + transport_tearoff_hbox.pack_start (punch_in_button, false, false); + transport_tearoff_hbox.pack_start (punch_out_button, false, false); + transport_tearoff_hbox.pack_start (auto_input_button, false, false); + transport_tearoff_hbox.pack_start (auto_return_button, false, false); + transport_tearoff_hbox.pack_start (auto_play_button, false, false); + transport_tearoff_hbox.pack_start (click_button, false, false); + transport_tearoff_hbox.pack_start (follow_button, false, false); + + /* desensitize */ + + set_transport_sensitivity (false); + + /* catch up with editor state */ + + follow_changed (); + +// transport_tearoff_hbox.pack_start (preroll_button, false, false); +// transport_tearoff_hbox.pack_start (preroll_clock, false, false); + +// transport_tearoff_hbox.pack_start (postroll_button, false, false); +// transport_tearoff_hbox.pack_start (postroll_clock, false, false); + + transport_tearoff_hbox.pack_start (alert_box, false, false, 5); +} + +void +ARDOUR_UI::setup_clock () +{ + ARDOUR_UI::Clock.connect (bind (slot (big_clock, &AudioClock::set), false)); + + big_clock_window = new BigClockWindow; + + big_clock_window->set_border_width (0); + big_clock_window->add (big_clock); + big_clock_window->set_title (_("ardour: clock")); + + big_clock_window->delete_event.connect (bind (slot (just_hide_it), static_cast(big_clock_window))); + big_clock_window->realize.connect (slot (*this, &ARDOUR_UI::big_clock_realize)); + big_clock_window->size_allocate.connect (slot (*this, &ARDOUR_UI::big_clock_size_event)); + + big_clock_window->Hiding.connect (slot (*this, &ARDOUR_UI::big_clock_hiding)); +} + +void +ARDOUR_UI::big_clock_size_event (GtkAllocation *alloc) +{ + return; +} + +void +ARDOUR_UI::big_clock_realize () +{ + big_clock_window->get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH|GDK_DECOR_MAXIMIZE|GDK_DECOR_MINIMIZE)); +} + +void +ARDOUR_UI::detach_tearoff (Gtk::Box* b, Gtk::Widget* w) +{ + editor->ensure_float (*transport_tearoff->tearoff_window()); + b->remove (*w); +} + +void +ARDOUR_UI::reattach_tearoff (Gtk::Box* b, Gtk::Widget* w, int32_t n) +{ + b->pack_start (*w); + b->reorder_child (*w, n); +} + +void +ARDOUR_UI::soloing_changed (bool onoff) +{ + if (solo_alert_button.get_active() != onoff) { + solo_alert_button.set_active (onoff); + } +} + +void +ARDOUR_UI::_auditioning_changed (bool onoff) +{ + if (auditioning_alert_button.get_active() != onoff) { + auditioning_alert_button.set_active (onoff); + set_transport_sensitivity (!onoff); + } +} + +void +ARDOUR_UI::auditioning_changed (bool onoff) +{ + Gtkmmext::UI::instance()->call_slot(bind (slot (*this, &ARDOUR_UI::_auditioning_changed), onoff)); +} + +void +ARDOUR_UI::audition_alert_toggle () +{ + if (session) { + session->cancel_audition(); + } +} + +void +ARDOUR_UI::solo_alert_toggle () +{ + if (session) { + session->set_all_solo (!session->soloing()); + } +} + +void +ARDOUR_UI::solo_blink (bool onoff) +{ + if (session == 0) { + return; + } + + if (session->soloing()) { + if (onoff) { + solo_alert_button.set_state (GTK_STATE_ACTIVE); + } else { + solo_alert_button.set_state (GTK_STATE_NORMAL); + } + } else { + solo_alert_button.set_active (false); + solo_alert_button.set_state (GTK_STATE_NORMAL); + } +} + +void +ARDOUR_UI::audition_blink (bool onoff) +{ + if (session == 0) { + return; + } + + if (session->is_auditioning()) { + if (onoff) { + auditioning_alert_button.set_state (GTK_STATE_ACTIVE); + } else { + auditioning_alert_button.set_state (GTK_STATE_NORMAL); + } + } else { + auditioning_alert_button.set_active (false); + auditioning_alert_button.set_state (GTK_STATE_NORMAL); + } +} + + +gint +ARDOUR_UI::shuttle_box_button_press (GdkEventButton* ev) +{ + if (!session) { + return TRUE; + } + + switch (ev->button) { + case 1: + Gtk::Main::grab_add (shuttle_box); + shuttle_grabbed = true; + mouse_shuttle (ev->x, true); + break; + + case 2: + case 3: + return TRUE; + break; + + case 4: + break; + case 5: + break; + } + + return TRUE; +} + +gint +ARDOUR_UI::shuttle_box_button_release (GdkEventButton* ev) +{ + if (!session) { + return TRUE; + } + + switch (ev->button) { + case 1: + mouse_shuttle (ev->x, true); + shuttle_grabbed = false; + Gtk::Main::grab_remove (shuttle_box); + if (shuttle_behaviour == Sprung) { + shuttle_fract = SHUTTLE_FRACT_SPEED1; + session->request_transport_speed (1.0); + shuttle_box.queue_draw (); + } + return TRUE; + + case 2: + if (session->transport_rolling()) { + shuttle_fract = SHUTTLE_FRACT_SPEED1; + session->request_transport_speed (1.0); + } else { + shuttle_fract = 0; + } + shuttle_box.queue_draw (); + return TRUE; + + case 3: + return TRUE; + + case 4: + shuttle_fract += 0.005; + break; + case 5: + shuttle_fract -= 0.005; + break; + } + + use_shuttle_fract (true); + + return TRUE; +} + +gint +ARDOUR_UI::shuttle_box_motion (GdkEventMotion* ev) +{ + if (!session || !shuttle_grabbed) { + return TRUE; + } + + return mouse_shuttle (ev->x, false); +} + +gint +ARDOUR_UI::mouse_shuttle (double x, bool force) +{ + double half_width = shuttle_box.width() / 2.0; + double distance = x - half_width; + + if (distance > 0) { + distance = min (distance, half_width); + } else { + distance = max (distance, -half_width); + } + + shuttle_fract = distance / half_width; + use_shuttle_fract (force); + return TRUE; +} + +void +ARDOUR_UI::use_shuttle_fract (bool force) +{ + struct timeval now; + struct timeval diff; + + /* do not attempt to submit a motion-driven transport speed request + more than once per process cycle. + */ + + gettimeofday (&now, 0); + timersub (&now, &last_shuttle_request, &diff); + + if (!force && (diff.tv_usec + (diff.tv_sec * 1000000)) < engine->usecs_per_cycle()) { + return; + } + + last_shuttle_request = now; + + bool neg = (shuttle_fract < 0.0); + + double fract = 1 - sqrt (1 - (shuttle_fract * shuttle_fract)); // Formula A1 + + if (neg) { + fract = -fract; + } + + session->request_transport_speed (8.0 * fract); // Formula A2 + shuttle_box.queue_draw (); +} + +gint +ARDOUR_UI::shuttle_box_expose (GdkEventExpose* event) +{ + gint x; + Gdk_Window win (shuttle_box.get_window()); + + /* redraw the background */ + + win.draw_rectangle (shuttle_box.get_style()->get_bg_gc (shuttle_box.get_state()), + true, + event->area.x, event->area.y, + event->area.width, event->area.height); + + + x = (gint) floor ((shuttle_box.width() / 2.0) + (0.5 * (shuttle_box.width() * shuttle_fract))); + + /* draw line */ + + win.draw_line (shuttle_box.get_style()->get_fg_gc (shuttle_box.get_state()), + x, + 0, + x, + shuttle_box.height()); + return TRUE; +} + +void +ARDOUR_UI::shuttle_style_clicked () +{ + shuttle_style_menu.popup (1, 0); +} + +void +ARDOUR_UI::shuttle_unit_clicked () +{ + shuttle_unit_menu.popup (1, 0); +} + +void +ARDOUR_UI::set_shuttle_units (ShuttleUnits u) +{ + switch ((shuttle_units = u)) { + case Percentage: + static_cast(shuttle_units_button.get_child())->set_text ("% "); + break; + case Semitones: + static_cast(shuttle_units_button.get_child())->set_text (_("st")); + break; + } +} + +void +ARDOUR_UI::set_shuttle_behaviour (ShuttleBehaviour b) +{ + switch ((shuttle_behaviour = b)) { + case Sprung: + static_cast(shuttle_style_button.get_child())->set_text (_("sprung")); + shuttle_fract = 0.0; + shuttle_box.queue_draw (); + if (session) { + if (session->transport_rolling()) { + shuttle_fract = SHUTTLE_FRACT_SPEED1; + session->request_transport_speed (1.0); + } + } + break; + case Wheel: + static_cast(shuttle_style_button.get_child())->set_text (_("wheel")); + break; + } +} + +void +ARDOUR_UI::update_speed_display () +{ + if (!session) { + speed_display_label.set_text (_("stopped")); + return; + } + + char buf[32]; + float x = session->transport_speed (); + + if (x != 0) { + if (shuttle_units == Percentage) { + snprintf (buf, sizeof (buf), "%.4f", x); + } else { + if (x < 0) { + snprintf (buf, sizeof (buf), "< %.1f", 12.0 * fast_log2 (-x)); + } else { + snprintf (buf, sizeof (buf), "> %.1f", 12.0 * fast_log2 (x)); + } + } + speed_display_label.set_text (buf); + } else { + speed_display_label.set_text (_("stopped")); + } +} + +void +ARDOUR_UI::set_transport_sensitivity (bool yn) +{ + goto_start_button.set_sensitive (yn); + goto_end_button.set_sensitive (yn); + roll_button.set_sensitive (yn); + stop_button.set_sensitive (yn); + play_selection_button.set_sensitive (yn); + rec_button.set_sensitive (yn); + auto_loop_button.set_sensitive (yn); + shuttle_box.set_sensitive (yn); +} diff --git a/gtk2_ardour/ardour_ui_dependents.cc b/gtk2_ardour/ardour_ui_dependents.cc new file mode 100644 index 0000000000..7464a67ce2 --- /dev/null +++ b/gtk2_ardour/ardour_ui_dependents.cc @@ -0,0 +1,109 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +/* this file exists solely to break compilation dependencies that + would connect changes to the mixer or editor objects. +*/ + +#include +#include +#include "ardour_ui.h" +#include "public_editor.h" +#include "mixer_ui.h" +#include "meter_bridge.h" +#include "keyboard.h" +#include "route_params_ui.h" +#include "i18n.h" + +using namespace SigC; + + +namespace ARDOUR { + class Session; + class Route; +} + +void +ARDOUR_UI::shutdown () +{ + if (session) { + delete session; + session = 0; + } + +} + +void +ARDOUR_UI::we_have_dependents () +{ + setup_keybindings (); +} + +void +ARDOUR_UI::setup_keybindings () +{ + /* install default bindings */ + + KeyboardTarget *defaults = new KeyboardTarget (editor->window(), X_("default")); + + XMLNode* keynode = ARDOUR::Config->get_keys(); + + if (keynode != 0) { + defaults->set_binding_state (*keynode); + editor->set_binding_state (*keynode); + mixer->set_binding_state (*keynode); + meter_bridge->set_binding_state (*keynode); + } else { + error << _("keyboard_target: error setting binding state: invalid node") << endmsg; + } + + /* use the default keyboard target for now */ + + keyboard->set_default_target (defaults); +} + +void +ARDOUR_UI::connect_dependents_to_session (ARDOUR::Session *s) +{ + editor->connect_to_session (s); + mixer->connect_to_session (s); + + meter_bridge->set_session (s); +} + +void +ARDOUR_UI::goto_editor_window () +{ + editor->show_window (); + editor->window().get_window().raise (); +} +void +ARDOUR_UI::goto_mixer_window () +{ + mixer->show_window (); + mixer->get_window().raise (); +} + +gint +ARDOUR_UI::exit_on_main_window_close (GdkEventAny *ev) +{ + finish(); + return TRUE; +} diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc new file mode 100644 index 0000000000..744a9bd031 --- /dev/null +++ b/gtk2_ardour/ardour_ui_dialogs.cc @@ -0,0 +1,454 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/* This file contains any ARDOUR_UI methods that require knowledge of + the various dialog boxes, and exists so that no compilation dependency + exists between the main ARDOUR_UI modules and their respective classes. + This is to cut down on the compile times. It also helps with my sanity. +*/ + +#include + +#include "ardour_ui.h" +#include "mixer_ui.h" +#include "meter_bridge.h" +#include "connection_editor.h" +#include "public_editor.h" +#include "option_editor.h" +#include "location_ui.h" +#include "route_params_ui.h" +#include "library_ui.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; +using namespace Gtkmmext; + +void +ARDOUR_UI::connect_to_session (Session *s) +{ + session = s; + + session->HaltOnXrun.connect (slot (*this, &ARDOUR_UI::halt_on_xrun_message)); + + /* sensitize menu bar options that are now valid */ + +// save_as_item->set_sensitive (true); + save_template_item->set_sensitive (true); + snapshot_item->set_sensitive (true); + save_item->set_sensitive (true); + add_track_item->set_sensitive (true); + export_item->set_sensitive (true); + close_item->set_sensitive (true); + locations_dialog_check->set_sensitive (true); + route_params_check->set_sensitive (true); + connection_editor_check->set_sensitive (true); + + cleanup_item->set_sensitive (true); + + /* sensitize transport bar */ + + goto_start_button.set_sensitive (true); + goto_end_button.set_sensitive (true); + roll_button.set_sensitive (true); + stop_button.set_sensitive (true); + play_selection_button.set_sensitive (true); + rec_button.set_sensitive (true); + auto_loop_button.set_sensitive (true); + shuttle_box.set_sensitive (true); + + /* */ + if (image_compositor_item) { + image_compositor_item->set_sensitive(true) ; + } + /* */ + + + if (session->n_diskstreams()) { + // meter_bridge_dialog_check->set_sensitive (true); + } else { + session->DiskStreamAdded.connect (slot (*this, &ARDOUR_UI::diskstream_added)); + } + + if (connection_editor) { + connection_editor->set_session (s); + } + + if (location_ui) { + location_ui->set_session(s); + } + + if (route_params) { + route_params->set_session (s); + } + + if (option_editor) { + option_editor->set_session (s); + } + + + Blink.connect (slot (*this, &ARDOUR_UI::transport_rec_enable_blink)); + Blink.connect (slot (*this, &ARDOUR_UI::solo_blink)); + Blink.connect (slot (*this, &ARDOUR_UI::audition_blink)); + + /* these are all need to be handled in an RT-safe and MT way, so don't + do any GUI work, just queue it for handling by the GUI thread. + */ + + session->TransportStateChange.connect (slot (*this, &ARDOUR_UI::queue_transport_change)); + session->ControlChanged.connect (slot (*this, &ARDOUR_UI::queue_map_control_change)); + + /* alert the user to these things happening */ + + session->AuditionActive.connect (slot (*this, &ARDOUR_UI::auditioning_changed)); + session->SoloActive.connect (slot (*this, &ARDOUR_UI::soloing_changed)); + + solo_alert_button.set_active (session->soloing()); + + /* can't be auditioning here */ + + primary_clock.set_session (s); + secondary_clock.set_session (s); + big_clock.set_session (s); + preroll_clock.set_session (s); + postroll_clock.set_session (s); + + /* Clocks are on by default after we are connected to a session, so show that here. + */ + + map_button_state (); + + connect_dependents_to_session (s); + + start_clocking (); + start_blinking (); + + if (editor) { + editor->window().realize(); + } + + transport_stopped (); + + second_connection = Main::timeout.connect (slot (*this, &ARDOUR_UI::every_second), 1000); + point_one_second_connection = Main::timeout.connect (slot (*this, &ARDOUR_UI::every_point_one_seconds), 100); + point_zero_one_second_connection = Main::timeout.connect (slot (*this, &ARDOUR_UI::every_point_zero_one_seconds), 40); +} + +int +ARDOUR_UI::unload_session () +{ + if (session && session->dirty()) { + switch (ask_about_saving_session (_("close session"))) { + case -1: + return 1; + + case 1: + session->save_state (""); + break; + } + } + + second_connection.disconnect (); + point_one_second_connection.disconnect (); + point_zero_one_second_connection.disconnect(); + + /* desensitize menu bar options that are now invalid */ + +// save_as_item->set_sensitive (false); + save_template_item->set_sensitive (false); + snapshot_item->set_sensitive (false); + save_item->set_sensitive (false); + add_track_item->set_sensitive (false); + export_item->set_sensitive (false); + close_item->set_sensitive (false); + // meter_bridge_dialog_check->set_sensitive (false); + connection_editor_check->set_sensitive (false); + locations_dialog_check->set_sensitive (false); + // meter_bridge_dialog_check->set_active(false); + connection_editor_check->set_active(false); + locations_dialog_check->set_active(false); + route_params_check->set_sensitive (false); + + /* desensitize transport bar */ + + goto_start_button.set_sensitive (false); + goto_end_button.set_sensitive (false); + roll_button.set_sensitive (false); + stop_button.set_sensitive (false); + play_selection_button.set_sensitive (false); + rec_button.set_sensitive (false); + auto_loop_button.set_sensitive (false); + shuttle_box.set_sensitive (false); + + stop_blinking (); + stop_clocking (); + + /* drop everything attached to the blink signal */ + + Blink.clear (); + + primary_clock.set_session (0); + secondary_clock.set_session (0); + big_clock.set_session (0); + preroll_clock.set_session (0); + postroll_clock.set_session (0); + + if (option_editor) { + option_editor->set_session (0); + } + + if (mixer) { + mixer->hide_all (); + } + + delete session; + session = 0; + + update_buffer_load (); + // update_disk_rate (); + + return 0; +} + +int +ARDOUR_UI::create_meter_bridge () +{ + if (meter_bridge == 0) { + meter_bridge = new MeterBridge (); + meter_bridge->Hiding.connect (slot (*this, &ARDOUR_UI::meter_bridge_hiding)); + } + return 0; +} + +void +ARDOUR_UI::meter_bridge_hiding() +{ + // meter_bridge_dialog_check->set_active(false); +} + +int +ARDOUR_UI::create_connection_editor () +{ + if (connection_editor == 0) { + connection_editor = new ConnectionEditor (); + connection_editor->Hiding.connect (slot (*this, &ARDOUR_UI::connection_editor_hiding)); + } + + if (session) { + connection_editor->set_session (session); + } + + return 0; +} + +void +ARDOUR_UI::toggle_connection_editor () +{ + if (create_connection_editor()) { + return; + } + + if (connection_editor->within_hiding()) { + return; + } + + + if (connection_editor_check->get_active()){ + connection_editor->show_all(); + } else { + connection_editor->hide_all(); + } +} + +void +ARDOUR_UI::connection_editor_hiding() +{ + connection_editor_check->set_active(false); +} + +void +ARDOUR_UI::big_clock_hiding() +{ + big_clock_check->set_active(false); +} + +void +ARDOUR_UI::toggle_big_clock_window () +{ + if (big_clock_window->within_hiding()) { + return; + } + + if (big_clock_window->is_visible()) { + big_clock_window->hide_all (); + } else { + big_clock_window->show_all (); + } +} + +void +ARDOUR_UI::toggle_options_window () +{ + if (option_editor == 0) { + option_editor = new OptionEditor (*this, *editor, *mixer); + option_editor->Hiding.connect(slot(*this, &ARDOUR_UI::option_hiding)); + option_editor->set_session (session); + } else if (option_editor->within_hiding()) { + return; + } + + if (option_editor->is_visible()) { + option_editor->hide_all (); + } else { + option_editor->show_all (); + } +} + +void +ARDOUR_UI::option_hiding () +{ + options_window_check->set_active(false); +} + +void +ARDOUR_UI::toggle_auto_input () + +{ + toggle_some_session_state (auto_input_button, + &Session::get_auto_input, + &Session::set_auto_input); + + meter_bridge->clear_all_meters (); +} + +void +ARDOUR_UI::toggle_metering () +{ +#if 0 + if (global_meter_button.get_active()) { + meter_bridge->toggle_metering (); + } +#endif +} + +int +ARDOUR_UI::create_location_ui () +{ + if (location_ui == 0) { + location_ui = new LocationUI (); + location_ui->set_session (session); + location_ui->Hiding.connect (slot (*this, &ARDOUR_UI::location_ui_hiding)); + } + return 0; +} + +void +ARDOUR_UI::toggle_location_window () +{ + if (create_location_ui()) { + return; + } + + if (location_ui->within_hiding()) { + return; + } + + if (location_ui->is_visible()) { + location_ui->hide_all(); + } else { + location_ui->show_all(); + } +} + +void +ARDOUR_UI::location_ui_hiding() +{ + locations_dialog_check->set_active(false); +} + +int +ARDOUR_UI::create_route_params () +{ + if (route_params == 0) { + route_params = new RouteParams_UI (*engine); + route_params->set_session (session); + route_params->Hiding.connect (slot (*this, &ARDOUR_UI::route_params_hiding)); + } + return 0; +} + +void +ARDOUR_UI::toggle_route_params_window () +{ + if (create_route_params ()) { + return; + } + + if (route_params->within_hiding()) { + return; + } + + if (route_params->is_visible ()) { + route_params->hide_all (); + } else { + route_params->show_all (); + } +} + +void +ARDOUR_UI::route_params_hiding () +{ + route_params_check->set_active (false); +} + +SoundFileSelector& +ARDOUR_UI::get_sfdb_window () +{ + if (sfdb_window == 0) { + sfdb_window = new SoundFileSelector (); + sfdb_window->Hiding.connect (slot (*this, &ARDOUR_UI::sfdb_hiding)); + sfdb_window->hide_all (); + } + + return *sfdb_window; +} + +void +ARDOUR_UI::toggle_sfdb_window () +{ + get_sfdb_window (); + + if (sfdb_window->within_hiding()) { + return; + } + + if (sfdb_window->is_visible ()) { + sfdb_window->hide_all (); + } else { + sfdb_window->show_all (); + sfdb_window->hide_import_stuff(); + } +} + +void +ARDOUR_UI::sfdb_hiding () +{ + sfdb_check->set_active (false); +} diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc new file mode 100644 index 0000000000..dab51b6349 --- /dev/null +++ b/gtk2_ardour/ardour_ui_ed.cc @@ -0,0 +1,315 @@ +/* + Copyright (C) 20002-2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +/* This file contains any ARDOUR_UI methods that require knowledge of + the editor, and exists so that no compilation dependency exists + between the main ARDOUR_UI modules and the PublicEditor class. This + is to cut down on the nasty compile times for both these classes. +*/ + +#include + +#include "ardour_ui.h" +#include "public_editor.h" +#include "audio_clock.h" +#include "editor.h" + +#include + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; +using namespace Gtkmmext; + +int +ARDOUR_UI::create_editor () + +{ + try { + editor = new Editor (*engine); + } + + catch (failed_constructor& err) { + return -1; + } + + editor->DisplayControlChanged.connect (slot (*this, &ARDOUR_UI::editor_display_control_changed)); + + return 0; +} + +void +ARDOUR_UI::build_menu_bar () + +{ + using namespace Menu_Helpers; + + menu_bar.set_name ("MainMenuBar"); + + MenuList& items = menu_bar.items(); + + /* file menu */ + + Menu *session_menu = manage (new Menu); + MenuList& session_items = session_menu->items(); + session_menu->set_name ("ArdourContextMenu"); + + session_items.push_back (MenuElem (_("New"), bind (slot (*this, &ARDOUR_UI::new_session), false, string ()))); + session_items.push_back (MenuElem (_("Open"), slot (*this, &ARDOUR_UI::open_session))); + session_items.push_back (MenuElem (_("Recent"), slot (*this, &ARDOUR_UI::open_recent_session))); + session_items.push_back (MenuElem (_("Close"), slot (*this, &ARDOUR_UI::close_session))); + close_item = session_items.back(); + close_item->set_sensitive (false); + + session_items.push_back (SeparatorElem()); + + session_items.push_back (MenuElem (_("Add Track/Bus"), slot (*this, &ARDOUR_UI::add_route))); + add_track_item = session_items.back (); + add_track_item->set_sensitive (false); + + session_items.push_back (SeparatorElem()); + + /* */ + + PathScanner scanner; + vector* results = scanner (getenv ("PATH"), "AniComp", false, false); + + if (results && !results->empty()) { + Menu* image_compositor_menu = manage(new Menu()); + MenuList& image_compositor_items = image_compositor_menu->items(); + image_compositor_menu->set_name ("ArdourContextMenu"); + image_compositor_items.push_back(MenuElem (_("Connect"), (slot (editor, &PublicEditor::connect_to_image_compositor)))) ; + session_items.push_back(MenuElem (_("Image Compositor"), *image_compositor_menu)) ; + image_compositor_item = session_items.back() ; + image_compositor_item->set_sensitive(false) ; + session_items.push_back (SeparatorElem()); + } else { + image_compositor_item = 0; + } + + if (results) { + delete results; + } + + /* */ + + session_items.push_back (MenuElem (_("Save"), bind (slot (*this, &ARDOUR_UI::save_state), string("")))); + save_item = session_items.back(); + save_item->set_sensitive (false); + + session_items.push_back (MenuElem (_("Snapshot"), slot (*this, &ARDOUR_UI::snapshot_session))); + snapshot_item = session_items.back(); + snapshot_item->set_sensitive (false); +/* + session_items.push_back (MenuElem (_("Save as..."))); + save_as_item = session_items.back(); + save_as_item->set_sensitive (false); +*/ + session_items.push_back (MenuElem (_("Save Template..."), slot (*this, &ARDOUR_UI::save_template))); + save_template_item = session_items.back(); + save_template_item->set_sensitive (false); + + Menu *export_menu = manage (new Menu); + MenuList& export_items = export_menu->items(); + export_menu->set_name ("ArdourContextMenu"); + export_items.push_back (MenuElem (_("Export session to audiofile..."), slot (*editor, &PublicEditor::export_session))); + export_items.push_back (MenuElem (_("Export range to audiofile..."), slot (*editor, &PublicEditor::export_selection))); + // export_items.back()->set_sensitive (false); + + session_items.push_back (MenuElem (_("Export"), *export_menu)); + export_item = session_items.back(); + export_item->set_sensitive (false); + + session_items.push_back (SeparatorElem()); + + Menu *cleanup_menu = manage (new Menu); + MenuList& cleanup_items = cleanup_menu->items(); + cleanup_menu->set_name ("ArdourContextMenu"); + cleanup_items.push_back (MenuElem (_("Cleanup unused sources"), slot (*(ARDOUR_UI::instance()), &ARDOUR_UI::cleanup))); + cleanup_items.push_back (MenuElem (_("Flush wastebasket"), slot (*(ARDOUR_UI::instance()), &ARDOUR_UI::flush_trash))); + + session_items.push_back (MenuElem (_("Cleanup"), *cleanup_menu)); + cleanup_item = session_items.back (); + cleanup_item->set_sensitive (false); + + session_items.push_back (SeparatorElem()); + + session_items.push_back (MenuElem (_("Quit"), slot (*(ARDOUR_UI::instance()), &ARDOUR_UI::finish))); + + items.push_back (MenuElem (_("Session"), *session_menu)); + + /* edit menu; the editor is responsible for the contents */ + + Menu *edit_menu = manage (new Menu); + editor->set_edit_menu (*edit_menu); + items.push_back (MenuElem (_("Edit"), *edit_menu)); + edit_menu->set_name ("ArdourContextMenu"); + + /* JACK menu for controlling ... JACK */ + + Menu* jack_menu = manage (new Menu); + MenuList& jack_items = jack_menu->items(); + jack_menu->set_name ("ArdourContextMenu"); + + jack_items.push_back (MenuElem (_("Disconnect"), slot (*(ARDOUR_UI::instance()), &ARDOUR_UI::disconnect_from_jack))); + jack_disconnect_item = jack_items.back(); + jack_disconnect_item->set_sensitive (false); + jack_items.push_back (MenuElem (_("Reconnect"), slot (*(ARDOUR_UI::instance()), &ARDOUR_UI::reconnect_to_jack))); + jack_reconnect_item = jack_items.back(); + jack_reconnect_item->set_sensitive (false); + + jack_bufsize_menu = manage (new Menu); + MenuList& jack_bufsize_items = jack_bufsize_menu->items(); + jack_bufsize_menu->set_name ("ArdourContextMenu"); + + jack_bufsize_items.push_back (MenuElem (X_("32"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 32))); + jack_bufsize_items.push_back (MenuElem (X_("64"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 64))); + jack_bufsize_items.push_back (MenuElem (X_("128"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 128))); + jack_bufsize_items.push_back (MenuElem (X_("256"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 256))); + jack_bufsize_items.push_back (MenuElem (X_("512"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 512))); + jack_bufsize_items.push_back (MenuElem (X_("1024"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 1024))); + jack_bufsize_items.push_back (MenuElem (X_("2048"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 2048))); + jack_bufsize_items.push_back (MenuElem (X_("4096"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 4096))); + jack_bufsize_items.push_back (MenuElem (X_("8192"), bind (slot (*this, &ARDOUR_UI::set_jack_buffer_size), (jack_nframes_t) 8192))); + + jack_items.push_back (MenuElem (_("Latency"), *jack_bufsize_menu)); + jack_bufsize_menu->set_sensitive (false); + + items.push_back (MenuElem (_("JACK"), *jack_menu)); + + /* windows menu */ + + Menu *window_menu = new Menu(); + MenuList& window_items = window_menu->items(); + window_menu->set_name ("ArdourContextMenu"); + + window_items.push_back (TearoffMenuElem()); + + window_items.push_back (MenuElem (_("Editor"), slot (*this, &ARDOUR_UI::goto_editor_window))); + window_items.push_back (MenuElem (_("Mixer"), slot (*this, &ARDOUR_UI::goto_mixer_window))); + + window_items.push_back (SeparatorElem()); + + window_items.push_back + (CheckMenuElem + (_("Options Editor"), + slot (*this, &ARDOUR_UI::toggle_options_window))); + options_window_check = dynamic_cast(window_items.back()); + // options_window_check->set_sensitive (false); + + window_items.push_back + (CheckMenuElem + (_("Audio Library"), + slot (*this, &ARDOUR_UI::toggle_sfdb_window))); + sfdb_check = dynamic_cast(window_items.back()); + + window_items.push_back + (CheckMenuElem + (_("Track/Bus Inspector"), + slot (*this, &ARDOUR_UI::toggle_route_params_window))); + route_params_check = dynamic_cast(window_items.back()); + route_params_check->set_sensitive (false); + + window_items.push_back + (CheckMenuElem + (_("Connections"), + slot (*this, &ARDOUR_UI::toggle_connection_editor))); + connection_editor_check = dynamic_cast(window_items.back()); + connection_editor_check->set_sensitive (false); + +#if 0 + window_items.push_back + (CheckMenuElem + (_("Meter Bridge"), + slot (*this, &ARDOUR_UI::toggle_meter_bridge_window))); + meter_bridge_dialog_check = dynamic_cast(window_items.back()); + meter_bridge_dialog_check->set_sensitive (false); +#endif + + window_items.push_back + (CheckMenuElem + (_("Locations"), + slot (*this, &ARDOUR_UI::toggle_location_window))); + locations_dialog_check = dynamic_cast(window_items.back()); + locations_dialog_check->set_sensitive (false); + + window_items.push_back + (CheckMenuElem + (_("Big Clock"), + slot (*this, &ARDOUR_UI::toggle_big_clock_window))); + big_clock_check = dynamic_cast(window_items.back()); + + window_items.push_back (SeparatorElem()); + + window_items.push_back (MenuElem (_("About"), slot (*this, &ARDOUR_UI::show_splash))); + + + items.push_back (MenuElem (_("Windows"), *window_menu)); + + wall_clock_box.add (wall_clock_label); + wall_clock_box.set_name ("WallClock"); + wall_clock_label.set_name ("WallClock"); + + disk_space_box.add (disk_space_label); + disk_space_box.set_name ("WallClock"); + disk_space_label.set_name ("WallClock"); + + cpu_load_box.add (cpu_load_label); + cpu_load_box.set_name ("CPULoad"); + cpu_load_label.set_name ("CPULoad"); + + buffer_load_box.add (buffer_load_label); + buffer_load_box.set_name ("BufferLoad"); + buffer_load_label.set_name ("BufferLoad"); + +// disk_rate_box.add (disk_rate_label); +// disk_rate_box.set_name ("DiskRate"); +// disk_rate_label.set_name ("DiskRate"); + + sample_rate_box.add (sample_rate_label); + sample_rate_box.set_name ("SampleRate"); + sample_rate_label.set_name ("SampleRate"); + + menu_hbox.pack_start (menu_bar, true, true); + menu_hbox.pack_end (wall_clock_box, false, false, 10); + menu_hbox.pack_end (disk_space_box, false, false, 10); + menu_hbox.pack_end (cpu_load_box, false, false, 10); +// menu_hbox.pack_end (disk_rate_box, false, false, 10); + menu_hbox.pack_end (buffer_load_box, false, false, 10); + menu_hbox.pack_end (sample_rate_box, false, false, 10); + + menu_bar_base.set_name ("MainMenuBar"); + menu_bar_base.add (menu_hbox); +} + + +void +ARDOUR_UI::editor_display_control_changed (Editing::DisplayControl c) +{ + switch (c) { + case Editing::FollowPlayhead: + follow_button.set_active (editor->follow_playhead ()); + break; + default: + break; + } +} + diff --git a/gtk2_ardour/ardour_ui_mixer.cc b/gtk2_ardour/ardour_ui_mixer.cc new file mode 100644 index 0000000000..8d92f70ae2 --- /dev/null +++ b/gtk2_ardour/ardour_ui_mixer.cc @@ -0,0 +1,45 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +/* This file contains any ARDOUR_UI methods that require knowledge of + the mixer, and exists so that no compilation dependency exists + between the main ARDOUR_UI modules and the mixer classes. This + is to cut down on the nasty compile times for these classes. +*/ + +#include "ardour_ui.h" +#include "mixer_ui.h" + +using namespace ARDOUR; + +int +ARDOUR_UI::create_mixer () + +{ + try { + mixer = new Mixer_UI (*engine); + } + + catch (failed_constructor& err) { + return -1; + } + + return 0; +} diff --git a/gtk2_ardour/arprof b/gtk2_ardour/arprof new file mode 100755 index 0000000000..984866a99b --- /dev/null +++ b/gtk2_ardour/arprof @@ -0,0 +1,9 @@ +#!/bin/sh + +if [ gprofhelper.c -nt gprofhelper.so ] ; then + echo "Recompiling gprof helper ..." + gcc -shared -nostdlib -fPIC gprofhelper.c -o gprofhelper.so -lpthread -ldl || exit 1 +fi + +export LD_LIBRARY_PATH=../libs/ardour/.libs +LDPRELOAD=./gprofhelper.so ./ardour $* diff --git a/gtk2_ardour/arval b/gtk2_ardour/arval new file mode 100755 index 0000000000..7c5c03ebd7 --- /dev/null +++ b/gtk2_ardour/arval @@ -0,0 +1,4 @@ +#!/bin/sh + +export LD_LIBRARY_PATH=../libs/ardour +exec valgrind --num-callers=12 --tool=memcheck ./ardour.bin --novst $* diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc new file mode 100644 index 0000000000..860e80af5d --- /dev/null +++ b/gtk2_ardour/audio_clock.cc @@ -0,0 +1,1698 @@ +/* + Copyright (C) 1999 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include // for sprintf +#include +#include + +#include +#include +#include + +#include "ardour_ui.h" +#include "audio_clock.h" +#include "utils.h" +#include "keyboard.h" +#include "i18n.h" + +using namespace ARDOUR; +using namespace SigC; +using namespace Gtk; + +const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = { + 2, /* SMPTE_Hours */ + 2, /* SMPTE_Minutes */ + 2, /* SMPTE_Seconds */ + 2, /* SMPTE_Frames */ + 2, /* MS_Hours */ + 2, /* MS_Minutes */ + 5, /* MS_Seconds */ + 3, /* Bars */ + 2, /* Beats */ + 4, /* Tick */ + 10 /* Audio Frame */ +}; + +AudioClock::AudioClock (const string& name, bool allow_edit, bool duration, bool with_tempo_and_meter) + : is_duration (duration), + editable (allow_edit), + colon1 (":"), + colon2 (":"), + colon3 (":"), + colon4 (":"), + colon5 (":"), + b1 ("|"), + b2 ("|") +{ + session = 0; + last_when = 0; + key_entry_state = 0; + ops_menu = 0; + dragging = false; + + audio_frames_ebox.add (audio_frames_label); + frames_packer_hbox.set_border_width (2); + frames_packer_hbox.pack_start (audio_frames_ebox, false, false); + + hours_ebox.add (hours_label); + minutes_ebox.add (minutes_label); + seconds_ebox.add (seconds_label); + frames_ebox.add (frames_label); + bars_ebox.add (bars_label); + beats_ebox.add (beats_label); + ticks_ebox.add (ticks_label); + ms_hours_ebox.add (ms_hours_label); + ms_minutes_ebox.add (ms_minutes_label); + ms_seconds_ebox.add (ms_seconds_label); + + smpte_packer.set_homogeneous (false); + smpte_packer.set_border_width (2); + smpte_packer.pack_start (hours_ebox, false, false); + smpte_packer.pack_start (colon1, false, false); + smpte_packer.pack_start (minutes_ebox, false, false); + smpte_packer.pack_start (colon2, false, false); + smpte_packer.pack_start (seconds_ebox, false, false); + smpte_packer.pack_start (colon3, false, false); + smpte_packer.pack_start (frames_ebox, false, false); + + smpte_packer_hbox.pack_start (smpte_packer, true, false); + + bbt_packer.set_homogeneous (false); + bbt_packer.set_border_width (2); + bbt_packer.pack_start (bars_ebox, false, false); + bbt_packer.pack_start (b1, false, false); + bbt_packer.pack_start (beats_ebox, false, false); + bbt_packer.pack_start (b2, false, false); + bbt_packer.pack_start (ticks_ebox, false, false); + + if (with_tempo_and_meter) { + meter_label = manage (new Label); + tempo_label = manage (new Label); + + meter_label->set_name ("BBTMeterLabel"); + tempo_label->set_name ("BBTTempoLabel"); + + tempo_meter_box.pack_start (*meter_label, false, false); + tempo_meter_box.pack_start (*tempo_label, false, false); + + bbt_packer.pack_start (tempo_meter_box, false, false, 5); + } else { + meter_label = 0; + tempo_label = 0; + } + + bbt_packer_hbox.pack_start (bbt_packer, true, false); + + minsec_packer.set_homogeneous (false); + minsec_packer.set_border_width (2); + minsec_packer.pack_start (ms_hours_ebox, false, false); + minsec_packer.pack_start (colon4, false, false); + minsec_packer.pack_start (ms_minutes_ebox, false, false); + minsec_packer.pack_start (colon5, false, false); + minsec_packer.pack_start (ms_seconds_ebox, false, false); + + minsec_packer_hbox.pack_start (minsec_packer, true, false); + + set_name (name); + clock_base.set_name (name); + + audio_frames_label.set_name (name); + hours_label.set_name (name); + minutes_label.set_name (name); + seconds_label.set_name (name); + frames_label.set_name (name); + bars_label.set_name (name); + beats_label.set_name (name); + ticks_label.set_name (name); + ms_hours_label.set_name (name); + ms_minutes_label.set_name (name); + ms_seconds_label.set_name (name); + hours_ebox.set_name (name); + minutes_ebox.set_name (name); + seconds_ebox.set_name (name); + frames_ebox.set_name (name); + audio_frames_ebox.set_name (name); + bars_ebox.set_name (name); + beats_ebox.set_name (name); + ticks_ebox.set_name (name); + ms_hours_ebox.set_name (name); + ms_minutes_ebox.set_name (name); + ms_seconds_ebox.set_name (name); + + colon1.set_name (name); + colon2.set_name (name); + colon3.set_name (name); + colon4.set_name (name); + colon5.set_name (name); + b1.set_name (name); + b2.set_name (name); + + clock_frame.set_shadow_type (GTK_SHADOW_IN); + clock_frame.set_name ("BaseFrame"); + + clock_frame.add (clock_base); + + _mode = BBT; /* lie to force mode switch */ + set_mode (SMPTE); + + pack_start (clock_frame, true, true); + + /* the clock base handles button releases for menu popup regardless of + editable status. if the clock is editable, the clock base is where + we pass focus to after leaving the last editable "field", which + will then shutdown editing till the user starts it up again. + + it does this because the focus out event on the field disables + keyboard event handling, and we don't connect anything up to + notice focus in on the clock base. hence, keyboard event handling + stays disabled. + */ + + clock_base.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + clock_base.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Hours)); + + if (editable) { + setup_events (); + } + + set (last_when, true); +} + +void +AudioClock::setup_events () +{ + clock_base.set_flags (GTK_CAN_FOCUS); + + hours_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); + minutes_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); + seconds_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); + frames_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); + bars_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); + beats_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); + ticks_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); + ms_hours_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); + ms_minutes_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); + ms_seconds_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); + audio_frames_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_FOCUS_CHANGE_MASK|GDK_POINTER_MOTION_MASK); + + hours_ebox.set_flags (GTK_CAN_FOCUS); + minutes_ebox.set_flags (GTK_CAN_FOCUS); + seconds_ebox.set_flags (GTK_CAN_FOCUS); + frames_ebox.set_flags (GTK_CAN_FOCUS); + audio_frames_ebox.set_flags (GTK_CAN_FOCUS); + bars_ebox.set_flags (GTK_CAN_FOCUS); + beats_ebox.set_flags (GTK_CAN_FOCUS); + ticks_ebox.set_flags (GTK_CAN_FOCUS); + ms_hours_ebox.set_flags (GTK_CAN_FOCUS); + ms_minutes_ebox.set_flags (GTK_CAN_FOCUS); + ms_seconds_ebox.set_flags (GTK_CAN_FOCUS); + + hours_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), SMPTE_Hours)); + minutes_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes)); + seconds_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds)); + frames_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), SMPTE_Frames)); + audio_frames_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), AudioFrames)); + bars_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), Bars)); + beats_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), Beats)); + ticks_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), Ticks)); + ms_hours_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), MS_Hours)); + ms_minutes_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), MS_Minutes)); + ms_seconds_ebox.motion_notify_event.connect (bind (slot (*this, &AudioClock::field_motion_notify_event), MS_Seconds)); + + hours_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), SMPTE_Hours)); + minutes_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), SMPTE_Minutes)); + seconds_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), SMPTE_Seconds)); + frames_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), SMPTE_Frames)); + audio_frames_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), AudioFrames)); + bars_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), Bars)); + beats_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), Beats)); + ticks_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), Ticks)); + ms_hours_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), MS_Hours)); + ms_minutes_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), MS_Minutes)); + ms_seconds_ebox.button_press_event.connect (bind (slot (*this, &AudioClock::field_button_press_event), MS_Seconds)); + + hours_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Hours)); + minutes_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Minutes)); + seconds_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Seconds)); + frames_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), SMPTE_Frames)); + audio_frames_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), AudioFrames)); + bars_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), Bars)); + beats_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), Beats)); + ticks_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), Ticks)); + ms_hours_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), MS_Hours)); + ms_minutes_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), MS_Minutes)); + ms_seconds_ebox.button_release_event.connect (bind (slot (*this, &AudioClock::field_button_release_event), MS_Seconds)); + + hours_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), SMPTE_Hours)); + minutes_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), SMPTE_Minutes)); + seconds_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), SMPTE_Seconds)); + frames_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), SMPTE_Frames)); + audio_frames_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), AudioFrames)); + bars_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), Bars)); + beats_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), Beats)); + ticks_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), Ticks)); + ms_hours_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), MS_Hours)); + ms_minutes_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), MS_Minutes)); + ms_seconds_ebox.key_release_event.connect (bind (slot (*this, &AudioClock::field_key_release_event), MS_Seconds)); + + hours_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), SMPTE_Hours)); + minutes_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), SMPTE_Minutes)); + seconds_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), SMPTE_Seconds)); + frames_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), SMPTE_Frames)); + audio_frames_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), AudioFrames)); + bars_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), Bars)); + beats_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), Beats)); + ticks_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), Ticks)); + ms_hours_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), MS_Hours)); + ms_minutes_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), MS_Minutes)); + ms_seconds_ebox.focus_in_event.connect (bind (slot (*this, &AudioClock::field_focus_in_event), MS_Seconds)); + + hours_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), SMPTE_Hours)); + minutes_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), SMPTE_Minutes)); + seconds_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), SMPTE_Seconds)); + frames_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), SMPTE_Frames)); + audio_frames_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), AudioFrames)); + bars_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), Bars)); + beats_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), Beats)); + ticks_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), Ticks)); + ms_hours_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), MS_Hours)); + ms_minutes_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), MS_Minutes)); + ms_seconds_ebox.focus_out_event.connect (bind (slot (*this, &AudioClock::field_focus_out_event), MS_Seconds)); + + Gtkmmext::set_usize_to_display_given_text (hours_label, "-88", 0, 2); + Gtkmmext::set_usize_to_display_given_text (minutes_label, "88", 0, 2); + Gtkmmext::set_usize_to_display_given_text (seconds_label, "88", 0, 2); + Gtkmmext::set_usize_to_display_given_text (frames_label, "88", 0, 2); + + Gtkmmext::set_usize_to_display_given_text (bars_label, "-888", 0, 2); + Gtkmmext::set_usize_to_display_given_text (beats_label, "88", 0, 2); + Gtkmmext::set_usize_to_display_given_text (ticks_label, "8888", 0, 2); + + Gtkmmext::set_usize_to_display_given_text (audio_frames_label, "4294967296", 0, 2); +} + +void +AudioClock::realize_impl () +{ + HBox::realize_impl (); +} + +void +AudioClock::set (jack_nframes_t when, bool force) +{ + + if ((!force && !is_visible()) || session == 0) { + return; + } + + if (when == last_when && !force) { + return; + } + + switch (_mode) { + case SMPTE: + set_smpte (when, force); + break; + + case BBT: + set_bbt (when, force); + break; + + case MinSec: + set_minsec (when, force); + break; + + case Frames: + set_frames (when, force); + break; + + case Off: + break; + } + + last_when = when; +} + +void +AudioClock::set_frames (jack_nframes_t when, bool force) +{ + char buf[32]; + snprintf (buf, sizeof (buf), "%u", when); + audio_frames_label.set_text (buf); +} + +void +AudioClock::set_minsec (jack_nframes_t when, bool force) +{ + char buf[32]; + jack_nframes_t left; + int hrs; + int mins; + float secs; + + left = when; + hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); + left -= (jack_nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (session->frame_rate() * 60.0f)); + left -= (jack_nframes_t) floor (mins * session->frame_rate() * 60.0f); + secs = left / (float) session->frame_rate(); + + if (force || hrs != ms_last_hrs) { + sprintf (buf, "%d", hrs); + ms_hours_label.set_text (buf); + ms_last_hrs = hrs; + } + + if (force || mins != ms_last_mins) { + sprintf (buf, "%d", mins); + ms_minutes_label.set_text (buf); + ms_last_mins = mins; + } + + if (force || secs != ms_last_secs) { + sprintf (buf, "%06.3f", secs); + ms_seconds_label.set_text (buf); + ms_last_secs = secs; + } +} + +void +AudioClock::set_smpte (jack_nframes_t when, bool force) +{ + char buf[32]; + SMPTE_Time smpte; + + if (is_duration) { + session->smpte_duration (when, smpte); + } else { + session->smpte_time (when, smpte); + } + + if (force || smpte.hours != last_hrs || smpte.negative != last_negative) { + if (smpte.negative) { + sprintf (buf, "-%02ld", smpte.hours); + } else { + sprintf (buf, " %02ld", smpte.hours); + } + hours_label.set_text (buf); + last_hrs = smpte.hours; + last_negative = smpte.negative; + } + + if (force || smpte.minutes != last_mins) { + sprintf (buf, "%02ld", smpte.minutes); + minutes_label.set_text (buf); + last_mins = smpte.minutes; + } + + if (force || smpte.seconds != last_secs) { + sprintf (buf, "%02ld", smpte.seconds); + seconds_label.set_text (buf); + last_secs = smpte.seconds; + } + + if (force || smpte.frames != last_frames) { + sprintf (buf, "%02ld", smpte.frames); + frames_label.set_text (buf); + last_frames = smpte.frames; + } +} + +void +AudioClock::set_bbt (jack_nframes_t when, bool force) +{ + char buf[16]; + BBT_Time bbt; + + session->tempo_map().bbt_time (when, bbt); + sprintf (buf, "%03" PRIu32, bbt.bars); + bars_label.set_text (buf); + sprintf (buf, "%02" PRIu32, bbt.beats); + beats_label.set_text (buf); + sprintf (buf, "%04" PRIu32, bbt.ticks); + ticks_label.set_text (buf); + + if (meter_label) { + TempoMap::Metric m (session->tempo_map().metric_at (when)); + sprintf (buf, "%-5.2f", m.tempo().beats_per_minute()); + tempo_label->set_text (buf); + sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor()); + meter_label->set_text (buf); + } +} + +void +AudioClock::set_session (Session *s) +{ + session = s; + + if (s) { + set (last_when, true); + } +} + +gint +AudioClock::field_key_release_event (GdkEventKey *ev, Field field) +{ + Label *label = 0; + string new_text; + char new_char = 0; + bool move_on = false; + + switch (field) { + case SMPTE_Hours: + label = &hours_label; + break; + case SMPTE_Minutes: + label = &minutes_label; + break; + case SMPTE_Seconds: + label = &seconds_label; + break; + case SMPTE_Frames: + label = &frames_label; + break; + + case AudioFrames: + label = &audio_frames_label; + break; + + case MS_Hours: + label = &ms_hours_label; + break; + case MS_Minutes: + label = &ms_minutes_label; + break; + case MS_Seconds: + label = &ms_seconds_label; + break; + + case Bars: + label = &bars_label; + break; + case Beats: + label = &beats_label; + break; + case Ticks: + label = &ticks_label; + break; + default: + return FALSE; + } + + switch (ev->keyval) { + case GDK_0: + case GDK_KP_0: + new_char = '0'; + break; + case GDK_1: + case GDK_KP_1: + new_char = '1'; + break; + case GDK_2: + case GDK_KP_2: + new_char = '2'; + break; + case GDK_3: + case GDK_KP_3: + new_char = '3'; + break; + case GDK_4: + case GDK_KP_4: + new_char = '4'; + break; + case GDK_5: + case GDK_KP_5: + new_char = '5'; + break; + case GDK_6: + case GDK_KP_6: + new_char = '6'; + break; + case GDK_7: + case GDK_KP_7: + new_char = '7'; + break; + case GDK_8: + case GDK_KP_8: + new_char = '8'; + break; + case GDK_9: + case GDK_KP_9: + new_char = '9'; + break; + + case GDK_period: + case GDK_KP_Decimal: + if (_mode == MinSec && field == MS_Seconds) { + new_char = '.'; + } else { + return FALSE; + } + break; + + case GDK_Return: + case GDK_KP_Enter: + case GDK_Tab: + move_on = true; + break; + + case GDK_Escape: + clock_base.grab_focus (); + return TRUE; + + default: + return FALSE; + } + + if (!move_on) { + + if (key_entry_state == 0) { + + /* initialize with a fresh new string */ + + if (field != AudioFrames) { + for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) { + new_text += '0'; + } + } else { + new_text = ""; + } + + } else { + + string existing = label->get_text(); + if (existing.length() >= field_length[field]) { + new_text = existing.substr (1, field_length[field] - 1); + } else { + new_text = existing.substr (0, field_length[field] - 1); + } + } + + new_text += new_char; + label->set_text (new_text); + key_entry_state++; + } + + if (key_entry_state == field_length[field]) { + move_on = true; + } + + if (move_on) { + + if (key_entry_state) { + + switch (field) { + case SMPTE_Hours: + case SMPTE_Minutes: + case SMPTE_Seconds: + case SMPTE_Frames: + // Check SMPTE fields for sanity (may also adjust fields) + smpte_sanitize_display(); + break; + default: + break; + } + + ValueChanged(); /* EMIT_SIGNAL */ + } + + /* move on to the next field. + */ + + switch (field) { + + /* SMPTE */ + + case SMPTE_Hours: + minutes_ebox.grab_focus (); + break; + case SMPTE_Minutes: + seconds_ebox.grab_focus (); + break; + case SMPTE_Seconds: + frames_ebox.grab_focus (); + break; + case SMPTE_Frames: + clock_base.grab_focus (); + break; + + /* audio frames */ + case AudioFrames: + clock_base.grab_focus (); + break; + + /* Min:Sec */ + + case MS_Hours: + ms_minutes_ebox.grab_focus (); + break; + case MS_Minutes: + ms_seconds_ebox.grab_focus (); + break; + case MS_Seconds: + clock_base.grab_focus (); + break; + + /* BBT */ + + case Bars: + beats_ebox.grab_focus (); + break; + case Beats: + ticks_ebox.grab_focus (); + break; + case Ticks: + clock_base.grab_focus (); + break; + + default: + break; + } + + } + + return TRUE; +} + +gint +AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field) +{ + ARDOUR_UI::instance()->allow_focus (true); + + key_entry_state = 0; + + switch (field) { + case SMPTE_Hours: + hours_ebox.set_flags (GTK_HAS_FOCUS); + hours_ebox.set_state (GTK_STATE_ACTIVE); + break; + case SMPTE_Minutes: + minutes_ebox.set_flags (GTK_HAS_FOCUS); + minutes_ebox.set_state (GTK_STATE_ACTIVE); + break; + case SMPTE_Seconds: + seconds_ebox.set_flags (GTK_HAS_FOCUS); + seconds_ebox.set_state (GTK_STATE_ACTIVE); + break; + case SMPTE_Frames: + frames_ebox.set_flags (GTK_HAS_FOCUS); + frames_ebox.set_state (GTK_STATE_ACTIVE); + break; + + case AudioFrames: + audio_frames_ebox.set_flags (GTK_HAS_FOCUS); + audio_frames_ebox.set_state (GTK_STATE_ACTIVE); + break; + + case MS_Hours: + ms_hours_ebox.set_flags (GTK_HAS_FOCUS); + ms_hours_ebox.set_state (GTK_STATE_ACTIVE); + break; + case MS_Minutes: + ms_minutes_ebox.set_flags (GTK_HAS_FOCUS); + ms_minutes_ebox.set_state (GTK_STATE_ACTIVE); + break; + case MS_Seconds: + ms_seconds_ebox.set_flags (GTK_HAS_FOCUS); + ms_seconds_ebox.set_state (GTK_STATE_ACTIVE); + break; + case Bars: + bars_ebox.set_flags (GTK_HAS_FOCUS); + bars_ebox.set_state (GTK_STATE_ACTIVE); + break; + case Beats: + beats_ebox.set_flags (GTK_HAS_FOCUS); + beats_ebox.set_state (GTK_STATE_ACTIVE); + break; + case Ticks: + ticks_ebox.set_flags (GTK_HAS_FOCUS); + ticks_ebox.set_state (GTK_STATE_ACTIVE); + break; + } + + return FALSE; +} + +gint +AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field) +{ + ARDOUR_UI::instance()->allow_focus (false); + + switch (field) { + + case SMPTE_Hours: + hours_ebox.unset_flags (GTK_HAS_FOCUS); + hours_ebox.set_state (GTK_STATE_NORMAL); + break; + case SMPTE_Minutes: + minutes_ebox.unset_flags (GTK_HAS_FOCUS); + minutes_ebox.set_state (GTK_STATE_NORMAL); + break; + case SMPTE_Seconds: + seconds_ebox.unset_flags (GTK_HAS_FOCUS); + seconds_ebox.set_state (GTK_STATE_NORMAL); + break; + case SMPTE_Frames: + frames_ebox.unset_flags (GTK_HAS_FOCUS); + frames_ebox.set_state (GTK_STATE_NORMAL); + break; + + case AudioFrames: + audio_frames_ebox.unset_flags (GTK_HAS_FOCUS); + audio_frames_ebox.set_state (GTK_STATE_NORMAL); + break; + + case MS_Hours: + ms_hours_ebox.unset_flags (GTK_HAS_FOCUS); + ms_hours_ebox.set_state (GTK_STATE_NORMAL); + break; + case MS_Minutes: + ms_minutes_ebox.unset_flags (GTK_HAS_FOCUS); + ms_minutes_ebox.set_state (GTK_STATE_NORMAL); + break; + case MS_Seconds: + ms_seconds_ebox.unset_flags (GTK_HAS_FOCUS); + ms_seconds_ebox.set_state (GTK_STATE_NORMAL); + break; + + case Bars: + bars_ebox.unset_flags (GTK_HAS_FOCUS); + bars_ebox.set_state (GTK_STATE_NORMAL); + break; + case Beats: + beats_ebox.unset_flags (GTK_HAS_FOCUS); + beats_ebox.set_state (GTK_STATE_NORMAL); + break; + case Ticks: + ticks_ebox.unset_flags (GTK_HAS_FOCUS); + ticks_ebox.set_state (GTK_STATE_NORMAL); + break; + } + + return FALSE; +} + +gint +AudioClock::field_button_release_event (GdkEventButton *ev, Field field) +{ + + + if (dragging) { + gdk_pointer_ungrab(GDK_CURRENT_TIME); + dragging = false; + if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){ + // we actually dragged so return without setting editing focus, or we shift clicked + + return TRUE; + } + } + + if (!editable) { + if (ops_menu == 0) { + build_ops_menu (); + } + ops_menu->popup (1, ev->time); + return TRUE; + } + + if (Keyboard::is_context_menu_event (ev)) { + if (ops_menu == 0) { + build_ops_menu (); + } + ops_menu->popup (1, ev->time); + return TRUE; + } + + switch (ev->button) { + case 1: + switch (field) { + case SMPTE_Hours: + hours_ebox.grab_focus(); + break; + case SMPTE_Minutes: + minutes_ebox.grab_focus(); + break; + case SMPTE_Seconds: + seconds_ebox.grab_focus(); + break; + case SMPTE_Frames: + frames_ebox.grab_focus(); + break; + + case AudioFrames: + audio_frames_ebox.grab_focus(); + break; + + case MS_Hours: + ms_hours_ebox.grab_focus(); + break; + case MS_Minutes: + ms_minutes_ebox.grab_focus(); + break; + case MS_Seconds: + ms_seconds_ebox.grab_focus(); + break; + + case Bars: + bars_ebox.grab_focus (); + break; + case Beats: + beats_ebox.grab_focus (); + break; + case Ticks: + ticks_ebox.grab_focus (); + break; + } + break; + + default: + break; + } + + return TRUE; +} + +gint +AudioClock::field_button_press_event (GdkEventButton *ev, Field field) +{ + if (session == 0) return FALSE; + + jack_nframes_t frames = 0; + + switch (ev->button) { + case 1: + if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) { + set (frames, true); + ValueChanged (); /* EMIT_SIGNAL */ + } + + /* make absolutely sure that the pointer is grabbed */ + gdk_pointer_grab(ev->window,FALSE , + GdkEventMask( GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK |GDK_BUTTON_RELEASE_MASK), + NULL,NULL,ev->time); + dragging = true; + drag_accum = 0; + drag_start_y = ev->y; + drag_y = ev->y; + break; + + case 2: + if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) { + set (frames, true); + ValueChanged (); /* EMIT_SIGNAL */ + } + break; + + case 3: + /* used for context sensitive menu */ + return FALSE; + break; + + case 4: + if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) { + frames = get_frames (field); + if (frames != 0) { + if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + frames *= 10; + } + set (current_time() + frames, true); + ValueChanged (); /* EMIT_SIGNAL */ + } + } + break; + + case 5: + if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) { + frames = get_frames (field); + if (frames != 0) { + if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + frames *= 10; + } + + if ((double)current_time() - (double)frames < 0.0) { + set (0, true); + } + else { + set (current_time() - frames, true); + } + + ValueChanged (); /* EMIT_SIGNAL */ + } + } + break; + + default: + return FALSE; + break; + } + + return TRUE; +} + +gint +AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field) +{ + if (session == 0 || !dragging) { + return FALSE; + } + + float pixel_frame_scale_factor = 0.2f; + +/* + if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + pixel_frame_scale_factor = 0.1f; + } + + + if (Keyboard::modifier_state_contains (ev->state, + Keyboard::Control|Keyboard::Alt)) { + + pixel_frame_scale_factor = 0.025f; + } +*/ + double y_delta = ev->y - drag_y; + + drag_accum += y_delta*pixel_frame_scale_factor; + + drag_y = ev->y; + + if (trunc(drag_accum) != 0) { + + jack_nframes_t frames; + jack_nframes_t pos ; + int dir; + dir = (drag_accum < 0 ? 1:-1); + pos = current_time(); + frames = get_frames (field,pos,dir); + + if (frames != 0 && frames * drag_accum < current_time()) { + + set ((jack_nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land + + } else { + set (0 , false); + + } + + drag_accum= 0; + ValueChanged(); /* EMIT_SIGNAL */ + + + } + + return TRUE; +} + +jack_nframes_t +AudioClock::get_frames (Field field,jack_nframes_t pos,int dir) +{ + + jack_nframes_t frames = 0; + BBT_Time bbt; + switch (field) { + case SMPTE_Hours: + frames = (jack_nframes_t) floor (3600.0 * session->frame_rate()); + break; + case SMPTE_Minutes: + frames = (jack_nframes_t) floor (60.0 * session->frame_rate()); + break; + case SMPTE_Seconds: + frames = session->frame_rate(); + break; + case SMPTE_Frames: + frames = (jack_nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second); + break; + + case AudioFrames: + frames = 1; + break; + + case MS_Hours: + frames = (jack_nframes_t) floor (3600.0 * session->frame_rate()); + break; + case MS_Minutes: + frames = (jack_nframes_t) floor (60.0 * session->frame_rate()); + break; + case MS_Seconds: + frames = session->frame_rate(); + break; + + case Bars: + bbt.bars = 1; + bbt.beats = 0; + bbt.ticks = 0; + frames = session->tempo_map().bbt_duration_at(pos,bbt,dir); + break; + case Beats: + bbt.bars = 0; + bbt.beats = 1; + bbt.ticks = 0; + frames = session->tempo_map().bbt_duration_at(pos,bbt,dir); + break; + case Ticks: + bbt.bars = 0; + bbt.beats = 0; + bbt.ticks = 1; + frames = session->tempo_map().bbt_duration_at(pos,bbt,dir); + break; + } + + return frames; +} + +jack_nframes_t +AudioClock::current_time (jack_nframes_t pos) const +{ + jack_nframes_t ret = 0; + + switch (_mode) { + case SMPTE: + ret = smpte_frame_from_display (); + break; + case BBT: + ret = bbt_frame_from_display (pos); + break; + + case MinSec: + ret = minsec_frame_from_display (); + break; + + case Frames: + ret = audio_frame_from_display (); + break; + + case Off: + break; + } + + return ret; +} + +jack_nframes_t +AudioClock::current_duration (jack_nframes_t pos) const +{ + jack_nframes_t ret = 0; + + switch (_mode) { + case SMPTE: + ret = smpte_frame_from_display (); + break; + case BBT: + ret = bbt_frame_duration_from_display (pos); + break; + + case MinSec: + ret = minsec_frame_from_display (); + break; + + case Frames: + ret = audio_frame_from_display (); + break; + + case Off: + break; + } + + return ret; +} + +void +AudioClock::smpte_sanitize_display() +{ + // Check SMPTE fields for sanity, possibly adjusting values + if (atoi(minutes_label.get_text()) > 59) { + minutes_label.set_text("59"); + } + + if (atoi(seconds_label.get_text()) > 59) { + seconds_label.set_text("59"); + } + + switch ((long)rint(session->smpte_frames_per_second)) { + case 24: + if (atoi(frames_label.get_text()) > 23) { + frames_label.set_text("23"); + } + break; + case 25: + if (atoi(frames_label.get_text()) > 24) { + frames_label.set_text("24"); + } + break; + case 30: + if (atoi(frames_label.get_text()) > 29) { + frames_label.set_text("29"); + } + break; + default: + break; + } + + if (session->smpte_drop_frames) { + if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) { + frames_label.set_text("02"); + } + } +} + +jack_nframes_t +AudioClock::smpte_frame_from_display () const +{ + if (session == 0) { + return 0; + } + + SMPTE_Time smpte; + jack_nframes_t sample; + + smpte.hours = atoi (hours_label.get_text()); + smpte.minutes = atoi (minutes_label.get_text()); + smpte.seconds = atoi (seconds_label.get_text()); + smpte.frames = atoi (frames_label.get_text()); + + session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ ); + + +#if 0 +#define SMPTE_SAMPLE_TEST_1 +#define SMPTE_SAMPLE_TEST_2 +#define SMPTE_SAMPLE_TEST_3 +#define SMPTE_SAMPLE_TEST_4 +#define SMPTE_SAMPLE_TEST_5 +#define SMPTE_SAMPLE_TEST_6 +#define SMPTE_SAMPLE_TEST_7 + + // Testcode for smpte<->sample conversions (P.S.) + SMPTE_Time smpte1; + jack_nframes_t sample1; + jack_nframes_t oldsample = 0; + SMPTE_Time smpte2; + jack_nframes_t sample_increment; + + sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second); + +#ifdef SMPTE_SAMPLE_TEST_1 + // Test 1: use_offset = false, use_subframes = false + cout << "use_offset = false, use_subframes = false" << endl; + for (int i = 0; i < 108003; i++) { + session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ ); + session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ ); + + if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) { + cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl; + cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + break; + } + + if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) { + cout << "ERROR: smpte2 not equal smpte1" << endl; + cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + break; + } + oldsample = sample1; + session->smpte_increment( smpte1 ); + } + + cout << "sample_increment: " << sample_increment << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; +#endif + +#ifdef SMPTE_SAMPLE_TEST_2 + // Test 2: use_offset = true, use_subframes = false + cout << "use_offset = true, use_subframes = false" << endl; + + smpte1.hours = 0; + smpte1.minutes = 0; + smpte1.seconds = 0; + smpte1.frames = 0; + smpte1.subframes = 0; + sample1 = oldsample = 0; + + session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ ); + cout << "Starting at sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl; + + for (int i = 0; i < 108003; i++) { + session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); + session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ ); + +// cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; +// cout << "sample: " << sample1 << endl; +// cout << "sample: " << sample1 << " -> "; +// cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + + if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) { + cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl; + cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + break; + } + + if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) { + cout << "ERROR: smpte2 not equal smpte1" << endl; + cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + break; + } + oldsample = sample1; + session->smpte_increment( smpte1 ); + } + + cout << "sample_increment: " << sample_increment << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; +#endif + +#ifdef SMPTE_SAMPLE_TEST_3 + // Test 3: use_offset = true, use_subframes = false, decrement + cout << "use_offset = true, use_subframes = false, decrement" << endl; + + session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ ); + cout << "Starting at sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl; + + for (int i = 0; i < 108003; i++) { + session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); + session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ ); + +// cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; +// cout << "sample: " << sample1 << endl; +// cout << "sample: " << sample1 << " -> "; +// cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + + if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) { + cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl; + cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + break; + } + + if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) { + cout << "ERROR: smpte2 not equal smpte1" << endl; + cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + break; + } + oldsample = sample1; + session->smpte_decrement( smpte1 ); + } + + cout << "sample_decrement: " << sample_increment << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; +#endif + + +#ifdef SMPTE_SAMPLE_TEST_4 + // Test 4: use_offset = true, use_subframes = true + cout << "use_offset = true, use_subframes = true" << endl; + + for (long sub = 5; sub < 80; sub += 5) { + smpte1.hours = 0; + smpte1.minutes = 0; + smpte1.seconds = 0; + smpte1.frames = 0; + smpte1.subframes = 0; + sample1 = oldsample = (sample_increment * sub) / 80; + + session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ ); + + cout << "starting at sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl; + + for (int i = 0; i < 108003; i++) { + session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ ); + session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ ); + + if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) { + cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl; + cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + //break; + } + + if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) { + cout << "ERROR: smpte2 not equal smpte1" << endl; + cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + break; + } + oldsample = sample1; + session->smpte_increment( smpte1 ); + } + + cout << "sample_increment: " << sample_increment << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + + for (int i = 0; i < 108003; i++) { + session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ ); + session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ ); + + if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) { + cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl; + cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + //break; + } + + if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) { + cout << "ERROR: smpte2 not equal smpte1" << endl; + cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + break; + } + oldsample = sample1; + session->smpte_decrement( smpte1 ); + } + + cout << "sample_decrement: " << sample_increment << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + } +#endif + + +#ifdef SMPTE_SAMPLE_TEST_5 + // Test 5: use_offset = true, use_subframes = false, increment seconds + cout << "use_offset = true, use_subframes = false, increment seconds" << endl; + + smpte1.hours = 0; + smpte1.minutes = 0; + smpte1.seconds = 0; + smpte1.frames = 0; + smpte1.subframes = 0; + sample1 = oldsample = 0; + sample_increment = session->frame_rate(); + + session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ ); + cout << "Starting at sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl; + + for (int i = 0; i < 3600; i++) { + session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); + session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ ); + +// cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; +// cout << "sample: " << sample1 << endl; +// cout << "sample: " << sample1 << " -> "; +// cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + +// if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) +// { +// cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl; +// break; +// } + + if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) { + cout << "ERROR: smpte2 not equal smpte1" << endl; + cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + break; + } + oldsample = sample1; + session->smpte_increment_seconds( smpte1 ); + } + + cout << "sample_increment: " << sample_increment << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; +#endif + + +#ifdef SMPTE_SAMPLE_TEST_6 + // Test 6: use_offset = true, use_subframes = false, increment minutes + cout << "use_offset = true, use_subframes = false, increment minutes" << endl; + + smpte1.hours = 0; + smpte1.minutes = 0; + smpte1.seconds = 0; + smpte1.frames = 0; + smpte1.subframes = 0; + sample1 = oldsample = 0; + sample_increment = session->frame_rate() * 60; + + session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ ); + cout << "Starting at sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl; + + for (int i = 0; i < 60; i++) { + session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); + session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ ); + +// cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; +// cout << "sample: " << sample1 << endl; +// cout << "sample: " << sample1 << " -> "; +// cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + +// if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) +// { +// cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl; +// break; +// } + + if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) { + cout << "ERROR: smpte2 not equal smpte1" << endl; + cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + break; + } + oldsample = sample1; + session->smpte_increment_minutes( smpte1 ); + } + + cout << "sample_increment: " << sample_increment << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; +#endif + +#ifdef SMPTE_SAMPLE_TEST_7 + // Test 7: use_offset = true, use_subframes = false, increment hours + cout << "use_offset = true, use_subframes = false, increment hours" << endl; + + smpte1.hours = 0; + smpte1.minutes = 0; + smpte1.seconds = 0; + smpte1.frames = 0; + smpte1.subframes = 0; + sample1 = oldsample = 0; + sample_increment = session->frame_rate() * 60 * 60; + + session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ ); + cout << "Starting at sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl; + + for (int i = 0; i < 10; i++) { + session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ ); + session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ ); + +// cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; +// cout << "sample: " << sample1 << endl; +// cout << "sample: " << sample1 << " -> "; +// cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + +// if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) +// { +// cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl; +// break; +// } + + if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) { + cout << "ERROR: smpte2 not equal smpte1" << endl; + cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> "; + cout << "sample: " << sample1 << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; + break; + } + oldsample = sample1; + session->smpte_increment_hours( smpte1 ); + } + + cout << "sample_increment: " << sample_increment << endl; + cout << "sample: " << sample1 << " -> "; + cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl; +#endif + +#endif + + return sample; +} + +jack_nframes_t +AudioClock::minsec_frame_from_display () const +{ + if (session == 0) { + return 0; + } + + int hrs = atoi (ms_hours_label.get_text()); + int mins = atoi (ms_minutes_label.get_text()); + float secs = atof (ms_seconds_label.get_text()); + + jack_nframes_t sr = session->frame_rate(); + + return (jack_nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr)); +} + +jack_nframes_t +AudioClock::bbt_frame_from_display (jack_nframes_t pos) const +{ + if (session == 0) { + error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg; + return 0; + } + + AnyTime any; + any.type = AnyTime::BBT; + + any.bbt.bars = atoi (bars_label.get_text()); + any.bbt.beats = atoi (beats_label.get_text()); + any.bbt.ticks = atoi (ticks_label.get_text()); + + jack_nframes_t ret = session->convert_to_frames_at (pos, any); + + return ret; +} + + +jack_nframes_t +AudioClock::bbt_frame_duration_from_display (jack_nframes_t pos) const +{ + if (session == 0) { + error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg; + return 0; + } + + BBT_Time bbt; + + + bbt.bars = atoi (bars_label.get_text()); + bbt.beats = atoi (beats_label.get_text()); + bbt.ticks = atoi (ticks_label.get_text()); + + return session->tempo_map().bbt_duration_at(pos,bbt,1); +} + +jack_nframes_t +AudioClock::audio_frame_from_display () const +{ + return (jack_nframes_t) atoi (audio_frames_label.get_text()); +} + +void +AudioClock::build_ops_menu () +{ + using namespace Menu_Helpers; + ops_menu = new Menu; + MenuList& ops_items = ops_menu->items(); + ops_menu->set_name ("ArdourContextMenu"); + + Menu *mode_menu = manage (new Menu); + MenuList& mode_items = mode_menu->items(); + mode_menu->set_name ("ArdourContextMenu"); + + mode_items.push_back (MenuElem (_("SMPTE"), bind (slot (*this, &AudioClock::set_mode), SMPTE))); + mode_items.push_back (MenuElem (_("Bars:Beats"), bind (slot (*this, &AudioClock::set_mode), BBT))); + mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (slot (*this, &AudioClock::set_mode), MinSec))); + mode_items.push_back (MenuElem (_("Audio Frames"), bind (slot (*this, &AudioClock::set_mode), Frames))); + mode_items.push_back (MenuElem (_("Off"), bind (slot (*this, &AudioClock::set_mode), Off))); + + ops_items.push_back (MenuElem (_("Mode"), *mode_menu)); +} + +void +AudioClock::set_mode (Mode m) +{ + /* slightly tricky: this is called from within the ARDOUR_UI + constructor by some of its clock members. at that time + the instance pointer is unset, so we have to be careful. + the main idea is to drop keyboard focus in case we had + started editing the clock and then we switch clock mode. + */ + + if (ARDOUR_UI::instance()) { + ARDOUR_UI::instance()->allow_focus (false); + } + + if (_mode == m) { + return; + } + switch (_mode) { + case SMPTE: + case BBT: + case MinSec: + case Frames: + clock_base.remove (); + break; + case Off: + break; + } + + _mode = m; + + switch (_mode) { + case SMPTE: + clock_base.add (smpte_packer_hbox); + break; + case BBT: + clock_base.add (bbt_packer_hbox); + break; + case MinSec: + clock_base.add (minsec_packer_hbox); + break; + case Frames: + clock_base.add (frames_packer_hbox); + case Off: + break; + } + + set (last_when, true); + clock_base.show_all (); + key_entry_state = 0; +} diff --git a/gtk2_ardour/audio_clock.h b/gtk2_ardour/audio_clock.h new file mode 100644 index 0000000000..b9c9be095d --- /dev/null +++ b/gtk2_ardour/audio_clock.h @@ -0,0 +1,176 @@ +/* + Copyright (C) 1999 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __audio_clock_h__ +#define __audio_clock_h__ + +#include +#include + +namespace ARDOUR { + class Session; +}; + +class AudioClock : public Gtk::HBox +{ + public: + enum Mode { + SMPTE, + BBT, + MinSec, + Frames, + Off, + }; + + AudioClock (const string& name, bool editable, bool is_duration = false, bool with_tempo_meter = false); + + Mode mode() const { return _mode; } + + void set (jack_nframes_t, bool force = false); + void set_mode (Mode); + + jack_nframes_t current_time (jack_nframes_t position = 0) const; + jack_nframes_t current_duration (jack_nframes_t position = 0) const; + void set_session (ARDOUR::Session *s); + + SigC::Signal0 ValueChanged; + + private: + ARDOUR::Session *session; + Mode _mode; + uint32_t key_entry_state; + bool is_duration; + bool editable; + + Gtk::Menu *ops_menu; + + Gtk::HBox smpte_packer_hbox; + Gtk::HBox smpte_packer; + + Gtk::HBox minsec_packer_hbox; + Gtk::HBox minsec_packer; + + Gtk::HBox bbt_packer_hbox; + Gtk::HBox bbt_packer; + + Gtk::HBox frames_packer_hbox; + + enum Field { + SMPTE_Hours, + SMPTE_Minutes, + SMPTE_Seconds, + SMPTE_Frames, + MS_Hours, + MS_Minutes, + MS_Seconds, + Bars, + Beats, + Ticks, + AudioFrames, + }; + + Gtk::EventBox audio_frames_ebox; + Gtk::Label audio_frames_label; + + Gtk::EventBox hours_ebox; + Gtk::EventBox minutes_ebox; + Gtk::EventBox seconds_ebox; + Gtk::EventBox frames_ebox; + + Gtk::EventBox ms_hours_ebox; + Gtk::EventBox ms_minutes_ebox; + Gtk::EventBox ms_seconds_ebox; + + Gtk::EventBox bars_ebox; + Gtk::EventBox beats_ebox; + Gtk::EventBox ticks_ebox; + + Gtk::Label hours_label; + Gtk::Label minutes_label; + Gtk::Label seconds_label; + Gtk::Label frames_label; + Gtk::Label colon1, colon2, colon3; + + Gtk::Label ms_hours_label; + Gtk::Label ms_minutes_label; + Gtk::Label ms_seconds_label; + Gtk::Label colon4, colon5; + + Gtk::Label bars_label; + Gtk::Label beats_label; + Gtk::Label ticks_label; + Gtk::Label b1; + Gtk::Label b2; + + Gtk::Label* tempo_label; + Gtk::Label* meter_label; + + Gtk::VBox tempo_meter_box; + + Gtk::EventBox clock_base; + Gtk::Frame clock_frame; + + jack_nframes_t last_when; + + long last_hrs; + long last_mins; + long last_secs; + long last_frames; + bool last_negative; + + long ms_last_hrs; + long ms_last_mins; + float ms_last_secs; + + bool dragging; + double drag_start_y; + double drag_y; + double drag_accum; + + void realize_impl (); + + gint field_motion_notify_event (GdkEventMotion *ev, Field); + gint field_button_press_event (GdkEventButton *ev, Field); + gint field_button_release_event (GdkEventButton *ev, Field); + gint field_key_release_event (GdkEventKey *, Field); + gint field_focus_in_event (GdkEventFocus *, Field); + gint field_focus_out_event (GdkEventFocus *, Field); + + void set_smpte (jack_nframes_t, bool); + void set_bbt (jack_nframes_t, bool); + void set_minsec (jack_nframes_t, bool); + void set_frames (jack_nframes_t, bool); + + jack_nframes_t get_frames (Field,jack_nframes_t pos = 0,int dir=1); + + void smpte_sanitize_display(); + jack_nframes_t smpte_frame_from_display () const; + jack_nframes_t bbt_frame_from_display (jack_nframes_t) const; + jack_nframes_t bbt_frame_duration_from_display (jack_nframes_t) const; + jack_nframes_t minsec_frame_from_display () const; + jack_nframes_t audio_frame_from_display () const; + + void build_ops_menu (); + void setup_events (); + + static const uint32_t field_length[(int)AudioFrames+1]; +}; + +#endif /* __audio_clock_h__ */ diff --git a/gtk2_ardour/audio_time_axis.cc b/gtk2_ardour/audio_time_axis.cc new file mode 100644 index 0000000000..c4bd90d332 --- /dev/null +++ b/gtk2_ardour/audio_time_axis.cc @@ -0,0 +1,2001 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ardour_ui.h" +#include "public_editor.h" +#include "audio_time_axis.h" +#include "streamview.h" +#include "canvas-simplerect.h" +#include "playlist_selector.h" +#include "plugin_selector.h" +#include "plugin_ui.h" +#include "regionview.h" +#include "automation_gain_line.h" +#include "automation_pan_line.h" +#include "automation_time_axis.h" +#include "redirect_automation_time_axis.h" +#include "gain_automation_time_axis.h" +#include "pan_automation_time_axis.h" +#include "redirect_automation_line.h" +#include "selection.h" +#include "point_selection.h" +#include "enums.h" +#include "utils.h" +#include "keyboard.h" +#include "rgb_macros.h" +#include "prompter.h" +#include "crossfade_view.h" +#include "gui_thread.h" + +#include + +#include "i18n.h" + +using namespace ARDOUR; +using namespace SigC; +using namespace LADSPA; +using namespace Gtk; +using namespace Editing; + +static const gchar * small_x_xpm[] = { +"11 11 2 1", +" c None", +". c #000000", +" ", +" ", +" . . ", +" . . ", +" . . ", +" . ", +" . . ", +" . . ", +" . . ", +" ", +" "}; + +AudioTimeAxisView::AudioTimeAxisView (PublicEditor& ed, Session& sess, Route& rt, Widget *canvas) + : AxisView(sess), + RouteUI(rt, sess, _("m"), _("s"), _("r")), // mute, solo, and record + TimeAxisView(sess,ed,(TimeAxisView*) 0, canvas), + parent_canvas (canvas), + button_table (3, 3), + edit_group_button (_("g")), // group + playlist_button (_("p")), + size_button (_("h")), // height + automation_button (_("a")), + visual_button (_("v")), + redirect_window ("redirect window"), + redirect_display (1) +{ + _has_state = true; + subplugin_menu.set_name ("ArdourContextMenu"); + playlist_menu = 0; + playlist_action_menu = 0; + automation_action_menu = 0; + gain_track = 0; + pan_track = 0; + view = 0; + timestretch_rect = 0; + waveform_item = 0; + pan_automation_item = 0; + gain_automation_item = 0; + no_redraw = false; + + view = new StreamView (*this); + + add_gain_automation_child (); + add_pan_automation_child (); + + ignore_toggle = false; + + rec_enable_button->set_active (false); + mute_button->set_active (false); + solo_button->set_active (false); + + rec_enable_button->set_name ("TrackRecordEnableButton"); + mute_button->set_name ("TrackMuteButton"); + solo_button->set_name ("SoloButton"); + edit_group_button.set_name ("TrackGroupButton"); + playlist_button.set_name ("TrackPlaylistButton"); + automation_button.set_name ("TrackAutomationButton"); + size_button.set_name ("TrackSizeButton"); + visual_button.set_name ("TrackVisualButton"); + hide_button.set_name ("TrackRemoveButton"); + + hide_button.add (*(manage (new Pixmap (small_x_xpm)))); + + _route.mute_changed.connect (slot (*this, &RouteUI::mute_changed)); + _route.solo_changed.connect (slot (*this, &RouteUI::solo_changed)); + _route.solo_safe_changed.connect (slot (*this, &RouteUI::solo_changed)); + + _route.panner().Changed.connect (slot (*this, &AudioTimeAxisView::update_pans)); + + solo_button->button_press_event.connect (slot (*this, &RouteUI::solo_press)); + solo_button->button_release_event.connect (slot (*this, &RouteUI::solo_release)); + mute_button->button_press_event.connect (slot (*this, &RouteUI::mute_press)); + mute_button->button_release_event.connect (slot (*this, &RouteUI::mute_release)); + rec_enable_button->button_press_event.connect (slot (*this, &RouteUI::rec_enable_press)); + edit_group_button.button_release_event.connect (slot (*this, &AudioTimeAxisView::edit_click)); + playlist_button.clicked.connect (slot (*this, &AudioTimeAxisView::playlist_click)); + automation_button.clicked.connect (slot (*this, &AudioTimeAxisView::automation_click)); + size_button.button_release_event.connect (slot (*this, &AudioTimeAxisView::size_click)); + visual_button.clicked.connect (slot (*this, &AudioTimeAxisView::visual_click)); + hide_button.clicked.connect (slot (*this, &AudioTimeAxisView::hide_click)); + + name_entry.activate.connect (slot (*this, &AudioTimeAxisView::name_entry_activated)); + name_entry.focus_out_event.connect (slot (*this, &AudioTimeAxisView::name_entry_focus_out_handler)); + name_entry.button_press_event.connect (slot (*this, &AudioTimeAxisView::name_entry_button_press_handler)); + name_entry.button_release_event.connect (slot (*this, &AudioTimeAxisView::name_entry_button_release_handler)); + name_entry.key_release_event.connect (slot (*this, &AudioTimeAxisView::name_entry_key_release_handler)); + + if (is_audio_track()) { + controls_table.attach (*rec_enable_button, 6, 7, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0); + } + controls_table.attach (*mute_button, 7, 8, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0); + controls_table.attach (*solo_button, 8, 9, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_FILL|GTK_EXPAND, 0, 0); + + controls_table.attach (edit_group_button, 7, 8, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0); + + ARDOUR_UI::instance()->tooltips().set_tip(*rec_enable_button, _("Record")); + ARDOUR_UI::instance()->tooltips().set_tip(*solo_button,_("Solo")); + ARDOUR_UI::instance()->tooltips().set_tip(*mute_button,_("Mute")); + ARDOUR_UI::instance()->tooltips().set_tip(edit_group_button,_("Edit Group")); + ARDOUR_UI::instance()->tooltips().set_tip(size_button,_("Display Height")); + ARDOUR_UI::instance()->tooltips().set_tip(playlist_button,_("Playlist")); + ARDOUR_UI::instance()->tooltips().set_tip(automation_button, _("Automation")); + ARDOUR_UI::instance()->tooltips().set_tip(visual_button, _("Visual options")); + ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("Hide this track")); + + label_view (); + + controls_table.attach (hide_button, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + controls_table.attach (visual_button, 1, 2, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + controls_table.attach (size_button, 2, 3, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + controls_table.attach (automation_button, 3, 4, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + + if (is_audio_track()) { + controls_table.attach (playlist_button, 6, 7, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + + } + + /* remove focus from the buttons */ + + automation_button.unset_flags (GTK_CAN_FOCUS); + solo_button->unset_flags (GTK_CAN_FOCUS); + mute_button->unset_flags (GTK_CAN_FOCUS); + edit_group_button.unset_flags (GTK_CAN_FOCUS); + size_button.unset_flags (GTK_CAN_FOCUS); + playlist_button.unset_flags (GTK_CAN_FOCUS); + hide_button.unset_flags (GTK_CAN_FOCUS); + visual_button.unset_flags (GTK_CAN_FOCUS); + + /* map current state of the route */ + + update_diskstream_display (); + solo_changed(0); + mute_changed(0); + redirects_changed (0); + reset_redirect_automation_curves (); + edit_group_menu_radio_group = 0; + y_position = -1; + + ensure_xml_node (); + + set_state (*xml_node); + + _route.mute_changed.connect (slot (*this, &RouteUI::mute_changed)); + _route.solo_changed.connect (slot (*this, &RouteUI::solo_changed)); + _route.redirects_changed.connect (slot (*this, &AudioTimeAxisView::redirects_changed)); + + _route.name_changed.connect (slot (*this, &AudioTimeAxisView::route_name_changed)); + + if (is_audio_track()) { + + /* track */ + + audio_track()->FreezeChange.connect (slot (*this, &AudioTimeAxisView::map_frozen)); + + audio_track()->diskstream_changed.connect (slot (*this, &AudioTimeAxisView::diskstream_changed)); + get_diskstream()->speed_changed.connect (slot (*this, &AudioTimeAxisView::speed_changed)); + + controls_ebox.set_name ("AudioTrackControlsBaseUnselected"); + controls_base_selected_name = "AudioTrackControlsBaseSelected"; + controls_base_unselected_name = "AudioTrackControlsBaseUnselected"; + + /* ask for notifications of any new RegionViews */ + + view->AudioRegionViewAdded.connect (slot (*this, &AudioTimeAxisView::region_view_added)); + + view->attach (); + + /* pick up the correct freeze state */ + + map_frozen (); + + } else { + + /* bus */ + + controls_ebox.set_name ("BusControlsBaseUnselected"); + controls_base_selected_name = "BusControlsBaseSelected"; + controls_base_unselected_name = "BusControlsBaseUnselected"; + } + + editor.ZoomChanged.connect (slot (*this, &AudioTimeAxisView::reset_samples_per_unit)); +} + +AudioTimeAxisView::~AudioTimeAxisView () +{ + GoingAway (); /* EMIT_SIGNAL */ + + if (playlist_menu) { + delete playlist_menu; + playlist_menu = 0; + } + + if (playlist_action_menu) { + delete playlist_action_menu; + playlist_action_menu = 0; + } + + vector_delete (&redirect_automation_curves); + + for (list::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { + delete *i; + } + + if (view) { + delete view; + view = 0; + } +} + +guint32 +AudioTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent) +{ + ensure_xml_node (); + xml_node->add_property ("shown_editor", "yes"); + + return TimeAxisView::show_at (y, nth, parent); +} + +void +AudioTimeAxisView::hide () +{ + ensure_xml_node (); + xml_node->add_property ("shown_editor", "no"); + + TimeAxisView::hide (); +} + +void +AudioTimeAxisView::set_playlist (AudioPlaylist *newplaylist) +{ + AudioPlaylist *pl; + + modified_connection.disconnect (); + state_changed_connection.disconnect (); + + if ((pl = dynamic_cast (playlist())) != 0) { + state_changed_connection = pl->StateChanged.connect (slot (*this, &AudioTimeAxisView::playlist_state_changed)); + modified_connection = pl->Modified.connect (slot (*this, &AudioTimeAxisView::playlist_modified)); + } +} + +void +AudioTimeAxisView::playlist_modified () +{ +} + +gint +AudioTimeAxisView::edit_click (GdkEventButton *ev) +{ + if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + _route.set_edit_group (0, this); + return FALSE; + } + + using namespace Menu_Helpers; + + MenuList& items = edit_group_menu.items (); + + items.clear (); + items.push_back (RadioMenuElem (edit_group_menu_radio_group, _("No group"), + bind (slot (*this, &AudioTimeAxisView::set_edit_group_from_menu), (RouteGroup *) 0))); + + if (_route.edit_group() == 0) { + static_cast(items.back())->set_active (); + } + + _session.foreach_edit_group (this, &AudioTimeAxisView::add_edit_group_menu_item); + edit_group_menu.popup (ev->button, ev->time); + + return FALSE; +} + +void +AudioTimeAxisView::add_edit_group_menu_item (RouteGroup *eg) +{ + using namespace Menu_Helpers; + + MenuList &items = edit_group_menu.items(); + items.push_back (RadioMenuElem (edit_group_menu_radio_group, + eg->name(), bind (slot (*this, &AudioTimeAxisView::set_edit_group_from_menu), eg))); + if (_route.edit_group() == eg) { + static_cast(items.back())->set_active (); + } +} + +void +AudioTimeAxisView::set_edit_group_from_menu (RouteGroup *eg) + +{ + _route.set_edit_group (eg, this); +} + +void +AudioTimeAxisView::playlist_state_changed (Change ignored) +{ + // ENSURE_GUI_THREAD (bind (slot (*this, &AudioTimeAxisView::playlist_state_changed), ignored)); + // why are we here ? +} + +void +AudioTimeAxisView::playlist_changed () + +{ + label_view (); + + if (is_audio_track()) { + set_playlist (get_diskstream()->playlist()); + } +} + +void +AudioTimeAxisView::label_view () +{ + string x = _route.name(); + + if (x != name_entry.get_text()) { + name_entry.set_text (x); + } + + ARDOUR_UI::instance()->tooltips().set_tip (name_entry, x); +} + +void +AudioTimeAxisView::route_name_changed (void *src) +{ + editor.route_name_changed (this); + label_view (); +} + +void +AudioTimeAxisView::take_name_changed (void *src) + +{ + if (src != this) { + label_view (); + } +} + +void +AudioTimeAxisView::playlist_click () +{ + // always build a new action menu + + if (playlist_action_menu == 0) { + playlist_action_menu = new Menu; + playlist_action_menu->set_name ("ArdourContextMenu"); + } + + build_playlist_menu(playlist_action_menu); + + playlist_action_menu->popup (1, 0); +} + +void +AudioTimeAxisView::automation_click () +{ + if (automation_action_menu == 0) { + /* this seems odd, but the automation action + menu is built as part of the display menu. + */ + build_display_menu (); + } + automation_action_menu->popup (1, 0); +} + +void +AudioTimeAxisView::show_timestretch (jack_nframes_t start, jack_nframes_t end) +{ + double x1; + double x2; + double y2; + + TimeAxisView::show_timestretch (start, end); + + hide_timestretch (); + +#if 0 + if (ts.empty()) { + return; + } + + + /* check that the time selection was made in our route, or our edit group. + remember that edit_group() == 0 implies the route is *not* in a edit group. + */ + + if (!(ts.track == this || (ts.group != 0 && ts.group == _route.edit_group()))) { + /* this doesn't apply to us */ + return; + } + + /* ignore it if our edit group is not active */ + + if ((ts.track != this) && _route.edit_group() && !_route.edit_group()->is_active()) { + return; + } +#endif + + if (timestretch_rect == 0) { + timestretch_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_display), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 0.0, + "y2", 0.0, + "fill_color_rgba", color_map[cTimeStretchFill], + "outline_color_rgba" , color_map[cTimeStretchOutline], + NULL); + } + + gtk_canvas_item_show (timestretch_rect); + gtk_canvas_item_raise_to_top (timestretch_rect); + + x1 = start / editor.get_current_zoom(); + x2 = (end - 1) / editor.get_current_zoom(); + y2 = height - 2; + + gtk_object_set (GTK_OBJECT(timestretch_rect), + "x1", x1, + "y1", 1.0, + "x2", x2, + "y2", y2, + NULL); +} + +void +AudioTimeAxisView::hide_timestretch () +{ + TimeAxisView::hide_timestretch (); + + if (timestretch_rect) { + gtk_canvas_item_hide (timestretch_rect); + } +} + +void +AudioTimeAxisView::show_selection (TimeSelection& ts) +{ + +#if 0 + /* ignore it if our edit group is not active or if the selection was started + in some other track or edit group (remember that edit_group() == 0 means + that the track is not in an edit group). + */ + + if (((ts.track != this && !is_child (ts.track)) && _route.edit_group() && !_route.edit_group()->is_active()) || + (!(ts.track == this || is_child (ts.track) || (ts.group != 0 && ts.group == _route.edit_group())))) { + hide_selection (); + return; + } +#endif + + TimeAxisView::show_selection (ts); +} + +void +AudioTimeAxisView::set_state (const XMLNode& node) +{ + const XMLProperty *prop; + + TimeAxisView::set_state (node); + + if ((prop = node.property ("shown_editor")) != 0) { + if (prop->value() == "no") { + _marked_for_display = false; + } else { + _marked_for_display = true; + } + } else { + _marked_for_display = true; + } + + XMLNodeList nlist = node.children(); + XMLNodeConstIterator niter; + XMLNode *child_node; + + + show_gain_automation = false; + show_pan_automation = false; + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + child_node = *niter; + + if (child_node->name() == "gain") { + XMLProperty *prop=child_node->property ("shown"); + + if (prop != 0) { + if (prop->value() == "yes") { + show_gain_automation = true; + } + } + continue; + } + + if (child_node->name() == "pan") { + XMLProperty *prop=child_node->property ("shown"); + + if (prop != 0) { + if (prop->value() == "yes") { + show_pan_automation = true; + } + } + continue; + } + } +} + +void +AudioTimeAxisView::set_height (TrackHeight h) +{ + bool height_changed = (h != (TrackHeight)height); + + TimeAxisView::set_height (h); + + ensure_xml_node (); + + view->set_height ((double) height); + + switch (height) { + case Largest: + xml_node->add_property ("track_height", "largest"); + controls_table.show_all (); + name_label.hide (); + break; + case Large: + xml_node->add_property ("track_height", "large"); + controls_table.show_all (); + name_label.hide (); + break; + case Larger: + xml_node->add_property ("track_height", "larger"); + controls_table.show_all (); + name_label.hide (); + break; + case Normal: + xml_node->add_property ("track_height", "normal"); + controls_table.show_all (); + name_label.hide (); + break; + case Smaller: + xml_node->add_property ("track_height", "smaller"); + controls_table.show_all (); + name_label.hide (); + edit_group_button.hide (); + hide_button.hide (); + visual_button.hide (); + size_button.hide (); + automation_button.hide (); + playlist_button.hide (); + break; + case Small: + xml_node->add_property ("track_height", "small"); + controls_table.hide_all (); + controls_table.show (); + name_label.set_text (_route.name()); + name_label.show (); + name_hbox.show (); + break; + } + + if (height_changed) { + /* only emit the signal if the height really changed */ + _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + } +} + +void +AudioTimeAxisView::select_track_color () +{ + if (RouteUI::choose_color ()) { + + if (view) { + view->apply_color (_color, StreamView::RegionColor); + } + } +} + +void +AudioTimeAxisView::reset_redirect_automation_curves () +{ + for (vector::iterator i = redirect_automation_curves.begin(); i != redirect_automation_curves.end(); ++i) { + (*i)->reset(); + } +} + +void +AudioTimeAxisView::reset_samples_per_unit () +{ + set_samples_per_unit (editor.get_current_zoom()); +} + +void +AudioTimeAxisView::set_samples_per_unit (double spu) +{ + double speed = 1.0; + + if (get_diskstream() != 0) { + speed = get_diskstream()->speed(); + } + + if (view) { + view->set_samples_per_unit (spu * speed); + } + + TimeAxisView::set_samples_per_unit (spu * speed); +} + +void +AudioTimeAxisView::build_display_menu () +{ + using namespace Menu_Helpers; + + /* get the size menu ready */ + + build_size_menu (); + + /* prepare it */ + + TimeAxisView::build_display_menu (); + + /* now fill it with our stuff */ + + MenuList& items = display_menu->items(); + display_menu->set_name ("ArdourContextMenu"); + + items.push_back (MenuElem (_("Height"), *size_menu)); + items.push_back (MenuElem (_("Color"), slot (*this, &AudioTimeAxisView::select_track_color))); + + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Hide all crossfades"), slot (*this, &AudioTimeAxisView::hide_all_xfades))); + items.push_back (MenuElem (_("Show all crossfades"), slot (*this, &AudioTimeAxisView::show_all_xfades))); + items.push_back (SeparatorElem()); + + + automation_action_menu = manage (new Menu); + MenuList& automation_items = automation_action_menu->items(); + automation_action_menu->set_name ("ArdourContextMenu"); + + automation_items.push_back (MenuElem (_("show all automation"), + slot (*this, &AudioTimeAxisView::show_all_automation))); + + automation_items.push_back (MenuElem (_("show existing automation"), + slot (*this, &AudioTimeAxisView::show_existing_automation))); + + automation_items.push_back (MenuElem (_("hide all automation"), + slot (*this, &AudioTimeAxisView::hide_all_automation))); + + automation_items.push_back (SeparatorElem()); + + automation_items.push_back (CheckMenuElem (_("gain"), + slot (*this, &AudioTimeAxisView::toggle_gain_track))); + gain_automation_item = static_cast (automation_items.back()); + gain_automation_item->set_active(show_gain_automation); + + automation_items.push_back (CheckMenuElem (_("pan"), + slot (*this, &AudioTimeAxisView::toggle_pan_track))); + pan_automation_item = static_cast (automation_items.back()); + pan_automation_item->set_active(show_pan_automation); + + automation_items.push_back (MenuElem (_("Plugins"), subplugin_menu)); + + items.push_back (MenuElem (_("Automation"), *automation_action_menu)); + + Menu *waveform_menu = manage(new Menu); + MenuList& waveform_items = waveform_menu->items(); + waveform_menu->set_name ("ArdourContextMenu"); + + waveform_items.push_back (CheckMenuElem (_("Show waveforms"), slot (*this, &AudioTimeAxisView::toggle_waveforms))); + waveform_item = static_cast (waveform_items.back()); + ignore_toggle = true; + waveform_item->set_active (editor.show_waveforms()); + ignore_toggle = false; + + RadioMenuItem::Group group; + + waveform_items.push_back (RadioMenuElem (group, _("Traditional"), bind (slot (*this, &AudioTimeAxisView::set_waveform_shape), Traditional))); + traditional_item = static_cast (waveform_items.back()); + + waveform_items.push_back (RadioMenuElem (group, _("Rectified"), bind (slot (*this, &AudioTimeAxisView::set_waveform_shape), Rectified))); + rectified_item = static_cast (waveform_items.back()); + + items.push_back (MenuElem (_("Waveform"), *waveform_menu)); + + if (is_audio_track()) { + + Menu* alignment_menu = manage (new Menu); + MenuList& alignment_items = alignment_menu->items(); + alignment_menu->set_name ("ArdourContextMenu"); + + RadioMenuItem::Group align_group; + + alignment_items.push_back (RadioMenuElem (align_group, _("align with existing material"), bind (slot (*this, &AudioTimeAxisView::set_align_style), ExistingMaterial))); + align_existing_item = dynamic_cast(alignment_items.back()); + if (get_diskstream()->alignment_style() == ExistingMaterial) { + align_existing_item->set_active(); + } + alignment_items.push_back (RadioMenuElem (align_group, _("align with capture time"), bind (slot (*this, &AudioTimeAxisView::set_align_style), CaptureTime))); + align_capture_item = dynamic_cast(alignment_items.back()); + if (get_diskstream()->alignment_style() == CaptureTime) { + align_capture_item->set_active(); + } + + items.push_back (MenuElem (_("Alignment"), *alignment_menu)); + + get_diskstream()->AlignmentStyleChanged.connect (slot (*this, &AudioTimeAxisView::align_style_changed)); + } + + items.push_back (SeparatorElem()); + items.push_back (CheckMenuElem (_("Active"), slot (*this, &RouteUI::toggle_route_active))); + route_active_menu_item = dynamic_cast (items.back()); + route_active_menu_item->set_active (_route.active()); + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Remove"), slot (*this, &RouteUI::remove_this_route))); + +} + +void +AudioTimeAxisView::align_style_changed () +{ + switch (get_diskstream()->alignment_style()) { + case ExistingMaterial: + if (!align_existing_item->get_active()) { + align_existing_item->set_active(); + } + break; + case CaptureTime: + if (!align_capture_item->get_active()) { + align_capture_item->set_active(); + } + break; + } +} + +void +AudioTimeAxisView::set_align_style (AlignStyle style) +{ + get_diskstream()->set_align_style (style); +} + +void +AudioTimeAxisView::rename_current_playlist () +{ + ArdourPrompter prompter (true); + + AudioPlaylist *pl; + DiskStream *ds; + + if (((ds = get_diskstream()) == 0) ||((pl = ds->playlist()) == 0)) { + return; + } + + prompter.set_prompt (_("Name for playlist")); + prompter.set_initial_text (pl->name()); + prompter.done.connect (Main::quit.slot()); + prompter.show_all (); + + Main::run (); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string name; + prompter.get_result (name); + pl->set_name (name); + } +} + +void +AudioTimeAxisView::playlist_selected (AudioPlaylist *pl) +{ + DiskStream *ds; + + if ((ds = get_diskstream()) != 0) { + ds->use_playlist (pl); + } +} + +void +AudioTimeAxisView::use_copy_playlist () +{ + AudioPlaylist *pl; + DiskStream *ds; + + if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) { + return; + } + + ArdourPrompter prompter (true); + string new_name = Playlist::bump_name (pl->name(), _session); + + prompter.set_prompt (_("Name for playlist")); + prompter.set_initial_text (new_name); + prompter.done.connect (Main::quit.slot()); + prompter.show_all (); + + Main::run (); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string name; + prompter.get_result (name); + + ds->use_copy_playlist (); + + pl = ds->playlist(); + pl->set_name (name); + } +} + +void +AudioTimeAxisView::use_new_playlist () +{ + AudioPlaylist *pl; + DiskStream *ds; + + if (((ds = get_diskstream()) == 0) || ((pl = ds->playlist()) == 0)) { + return; + } + + ArdourPrompter prompter (true); + string new_name = Playlist::bump_name (pl->name(), _session); + + prompter.set_prompt (_("Name for playlist")); + prompter.set_initial_text (new_name); + prompter.done.connect (Main::quit.slot()); + prompter.show_all (); + + Main::run (); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string name; + prompter.get_result (name); + + ds->use_new_playlist (); + + pl = ds->playlist(); + pl->set_name (name); + } +} + +void +AudioTimeAxisView::clear_playlist () +{ + AudioPlaylist *pl; + DiskStream *ds; + + if ((ds = get_diskstream()) != 0) { + if ((pl = ds->playlist()) != 0) { + editor.clear_playlist (*pl); + } + } +} + +void +AudioTimeAxisView::toggle_waveforms () +{ + if (view && waveform_item && !ignore_toggle) { + view->set_show_waveforms (waveform_item->is_active()); + } +} + +void +AudioTimeAxisView::set_show_waveforms (bool yn) +{ + if (waveform_item) { + waveform_item->set_active (yn); + } else { + view->set_show_waveforms (yn); + } +} + +void +AudioTimeAxisView::set_show_waveforms_recording (bool yn) +{ + if (view) { + view->set_show_waveforms_recording (yn); + } +} + +void +AudioTimeAxisView::set_waveform_shape (WaveformShape shape) +{ + if (view) { + view->set_waveform_shape (shape); + } +} + +void +AudioTimeAxisView::speed_changed () +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &AudioTimeAxisView::reset_samples_per_unit)); +} + +void +AudioTimeAxisView::diskstream_changed (void *src) +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &AudioTimeAxisView::update_diskstream_display)); +} + +void +AudioTimeAxisView::update_diskstream_display () +{ + DiskStream *ds; + + if ((ds = get_diskstream()) != 0) { + set_playlist (ds->playlist ()); + } + + map_frozen (); +} + +void +AudioTimeAxisView::selection_click (GdkEventButton* ev) +{ + PublicEditor::TrackViewList* tracks = editor.get_valid_views (this, _route.edit_group()); + + if (Keyboard::modifier_state_contains (ev->state, Keyboard::Shift)) { + if (editor.get_selection().selected (this)) { + editor.get_selection().remove (*tracks); + } else { + editor.get_selection().add (*tracks); + } + } else { + editor.get_selection().set (*tracks); + } + + delete tracks; +} + +void +AudioTimeAxisView::set_selected_regionviews (AudioRegionSelection& regions) +{ + if (view) { + view->set_selected_regionviews (regions); + } +} + +void +AudioTimeAxisView::set_selected_points (PointSelection& points) +{ + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + (*i)->set_selected_points (points); + } +} + +void +AudioTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list& results) +{ + double speed = 1.0; + + if (get_diskstream() != 0) { + speed = get_diskstream()->speed(); + } + + jack_nframes_t start_adjusted = (jack_nframes_t) (start * speed); + jack_nframes_t end_adjusted = (jack_nframes_t) (end * speed); + + if (view && touched (top, bot)) { + view->get_selectables (start_adjusted, end_adjusted, results); + } + + /* pick up visible automation tracks */ + + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + if (!(*i)->hidden()) { + (*i)->get_selectables (start_adjusted, end_adjusted, top, bot, results); + } + } +} + +void +AudioTimeAxisView::get_inverted_selectables (Selection& sel, list& results) +{ + if (view) { + view->get_inverted_selectables (sel, results); + } + + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + if (!(*i)->hidden()) { + (*i)->get_inverted_selectables (sel, results); + } + } + + return; +} + +RouteGroup* +AudioTimeAxisView::edit_group() const +{ + return _route.edit_group(); +} + +string +AudioTimeAxisView::name() const +{ + return _route.name(); +} + +Playlist * +AudioTimeAxisView::playlist () const +{ + DiskStream *ds; + + if ((ds = get_diskstream()) != 0) { + return ds->playlist(); + } else { + return 0; + } +} + +gint +AudioTimeAxisView::name_entry_button_press_handler (GdkEventButton *ev) +{ + if (ev->button == 3) { + return stop_signal (name_entry, "button_press_event"); + } + return FALSE; +} + +gint +AudioTimeAxisView::name_entry_button_release_handler (GdkEventButton *ev) +{ + return FALSE; +} + +gint +AudioTimeAxisView::name_entry_focus_out_handler (GdkEventFocus* ev) +{ + name_entry_changed (); + return TRUE; +} + +gint +AudioTimeAxisView::name_entry_key_release_handler (GdkEventKey* ev) +{ + switch (ev->keyval) { + case GDK_Tab: + case GDK_Up: + case GDK_Down: + name_entry_changed (); + return TRUE; + + default: + return FALSE; + } +} + +void +AudioTimeAxisView::name_entry_activated () +{ + /* this should drop focus from the entry, + and cause a call to name_entry_changed() + */ + controls_ebox.grab_focus(); +} + +void +AudioTimeAxisView::name_entry_changed () +{ + string x; + + ARDOUR_UI::generic_focus_out_event (0); + + x = name_entry.get_text (); + + if (x == _route.name()) { + return; + } + + if (x.length() == 0) { + name_entry.set_text (_route.name()); + return; + } + + strip_whitespace_edges(x); + + if (_session.route_name_unique (x)) { + _route.set_name (x, this); + } else { + ARDOUR_UI::instance()->popup_error (_("a track already exists with that name")); + name_entry.set_text (_route.name()); + } +} + +void +AudioTimeAxisView::visual_click () +{ + popup_display_menu (0); +} + +void +AudioTimeAxisView::hide_click () +{ + editor.unselect_strip_in_display (*this); +} + +Region* +AudioTimeAxisView::find_next_region (jack_nframes_t pos, RegionPoint point, int32_t dir) +{ + DiskStream *stream; + AudioPlaylist *playlist; + + if ((stream = get_diskstream()) != 0 && (playlist = stream->playlist()) != 0) { + return playlist->find_next_region (pos, point, dir); + } + + return 0; +} + +void +AudioTimeAxisView::add_gain_automation_child () +{ + XMLProperty* prop; + AutomationLine* line; + + gain_track = new GainAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, _("gain"), + _route.gain_automation_curve()); + + + line = new AutomationGainLine ("automation gain", _session, *gain_track, + gain_track->canvas_display, + _route.gain_automation_curve(), + PublicEditor::canvas_control_point_event, + PublicEditor::canvas_line_event); + line->set_line_color (color_map[cAutomationLine]); + + + gain_track->add_line (*line); + + add_child (gain_track); + + gain_track->Hiding.connect (slot (*this, &AudioTimeAxisView::gain_hidden)); + + bool hideit = true; + + XMLNode* node; + + if ((node = gain_track->get_state_node()) != 0) { + if ((prop = node->property ("shown")) != 0) { + if (prop->value() == "yes") { + hideit = false; + } + } + } + + if (hideit) { + gain_track->hide (); + } +} + +void +AudioTimeAxisView::add_pan_automation_child () +{ + XMLProperty* prop; + + pan_track = new PanAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, _("pan")); + + update_pans (); + + add_child (pan_track); + + pan_track->Hiding.connect (slot (*this, &AudioTimeAxisView::pan_hidden)); + + ensure_xml_node (); + bool hideit = true; + + XMLNode* node; + + if ((node = pan_track->get_state_node()) != 0) { + if ((prop = node->property ("shown")) != 0) { + if (prop->value() == "yes") { + hideit = false; + } + } + } + + if (hideit) { + pan_track->hide (); + } +} + +void +AudioTimeAxisView::update_pans () +{ + Panner::iterator p; + + pan_track->clear_lines (); + + /* we don't draw lines for "greater than stereo" panning. + */ + + if (_route.n_outputs() > 2) { + return; + } + + for (p = _route.panner().begin(); p != _route.panner().end(); ++p) { + + AutomationLine* line; + + line = new AutomationPanLine ("automation pan", _session, *pan_track, + pan_track->canvas_display, + (*p)->automation(), + PublicEditor::canvas_control_point_event, + PublicEditor::canvas_line_event); + + if (p == _route.panner().begin()) { + /* first line is a nice orange */ + line->set_line_color (color_map[cLeftPanAutomationLine]); + } else { + /* second line is a nice blue */ + line->set_line_color (color_map[cRightPanAutomationLine]); + } + + pan_track->add_line (*line); + } +} + +void +AudioTimeAxisView::toggle_gain_track () +{ + + bool showit = gain_automation_item->get_active(); + + if (showit != gain_track->marked_for_display()) { + if (showit) { + gain_track->set_marked_for_display (true); + gtk_canvas_item_show (gain_track->canvas_display); + gain_track->get_state_node()->add_property ("shown", X_("yes")); + } else { + gain_track->set_marked_for_display (false); + gain_track->hide (); + gain_track->get_state_node()->add_property ("shown", X_("no")); + } + + /* now trigger a redisplay */ + + if (!no_redraw) { + _route.gui_changed (X_("track_height"), (void *) 0); /* EMIT_SIGNAL */ + } + } +} + +void +AudioTimeAxisView::gain_hidden () +{ + gain_track->get_state_node()->add_property (X_("shown"), X_("no")); + + if (gain_automation_item && !_hidden) { + gain_automation_item->set_active (false); + } + + _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ +} + +void +AudioTimeAxisView::toggle_pan_track () +{ + bool showit = pan_automation_item->get_active(); + + if (showit != pan_track->marked_for_display()) { + if (showit) { + pan_track->set_marked_for_display (true); + gtk_canvas_item_show (pan_track->canvas_display); + pan_track->get_state_node()->add_property ("shown", X_("yes")); + } else { + pan_track->set_marked_for_display (false); + pan_track->hide (); + pan_track->get_state_node()->add_property ("shown", X_("no")); + } + + /* now trigger a redisplay */ + + if (!no_redraw) { + _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + } + } +} + +void +AudioTimeAxisView::pan_hidden () +{ + pan_track->get_state_node()->add_property ("shown", "no"); + + if (pan_automation_item && !_hidden) { + pan_automation_item->set_active (false); + } + + _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ +} + +AudioTimeAxisView::RedirectAutomationInfo::~RedirectAutomationInfo () +{ + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + delete *i; + } +} + + +AudioTimeAxisView::RedirectAutomationNode::~RedirectAutomationNode () +{ + parent.remove_ran (this); + + if (view) { + delete view; + } +} + +void +AudioTimeAxisView::remove_ran (RedirectAutomationNode* ran) +{ + if (ran->view) { + remove_child (ran->view); + } +} + +AudioTimeAxisView::RedirectAutomationNode* +AudioTimeAxisView::find_redirect_automation_node (Redirect *redirect, uint32_t what) +{ + for (list::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { + + if ((*i)->redirect == redirect) { + + for (vector::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { + if ((*ii)->what == what) { + return *ii; + } + } + } + } + + return 0; +} + +static string +legalize_for_xml_node (string str) +{ + string::size_type pos; + string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=:"; + string legal; + + legal = str; + pos = 0; + + while ((pos = legal.find_first_not_of (legal_chars, pos)) != string::npos) { + legal.replace (pos, 1, "_"); + pos += 1; + } + + return legal; +} + + +void +AudioTimeAxisView::add_redirect_automation_curve (Redirect *redirect, uint32_t what) +{ + RedirectAutomationLine* ral; + string name; + RedirectAutomationNode* ran; + + if ((ran = find_redirect_automation_node (redirect, what)) == 0) { + fatal << _("programming error: ") + << compose (X_("redirect automation curve for %1:%2 not registered with audio track!"), + redirect->name(), what) + << endmsg; + /*NOTREACHED*/ + return; + } + + if (ran->view) { + return; + } + + name = redirect->describe_parameter (what); + + /* create a string that is a legal XML node name that can be used to refer to this redirect+port combination */ + + char state_name[256]; + snprintf (state_name, sizeof (state_name), "Redirect-%s-%" PRIu32, legalize_for_xml_node (redirect->name()).c_str(), what); + + ran->view = new RedirectAutomationTimeAxisView (_session, _route, editor, *this, parent_canvas, name, what, *redirect, state_name); + + ral = new RedirectAutomationLine (name, + *redirect, what, _session, *ran->view, + ran->view->canvas_display, redirect->automation_list (what), + PublicEditor::canvas_control_point_event, + PublicEditor::canvas_line_event); + + ral->set_line_color (color_map[cRedirectAutomationLine]); + ral->queue_reset (); + + ran->view->add_line (*ral); + + ran->view->Hiding.connect (bind (slot (*this, &AudioTimeAxisView::redirect_automation_track_hidden), ran, redirect)); + + if (!ran->view->marked_for_display()) { + ran->view->hide (); + } else { + ran->menu_item->set_active (true); + } + + add_child (ran->view); + + view->foreach_regionview (bind (slot (*this, &AudioTimeAxisView::add_ghost_to_redirect), ran->view)); + + redirect->mark_automation_visible (what, true); +} + +void +AudioTimeAxisView::redirect_automation_track_hidden (AudioTimeAxisView::RedirectAutomationNode* ran, Redirect* r) +{ + if (!_hidden) { + ran->menu_item->set_active (false); + } + + r->mark_automation_visible (ran->what, false); + + _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ +} + +void +AudioTimeAxisView::add_existing_redirect_automation_curves (Redirect *redirect) +{ + set s; + RedirectAutomationLine *ral; + + redirect->what_has_visible_automation (s); + + for (set::iterator i = s.begin(); i != s.end(); ++i) { + + if ((ral = find_redirect_automation_curve (redirect, *i)) != 0) { + ral->queue_reset (); + } else { + add_redirect_automation_curve (redirect, (*i)); + } + } +} + +void +AudioTimeAxisView::add_redirect_to_subplugin_menu (Redirect* r) +{ + using namespace Menu_Helpers; + RedirectAutomationInfo *rai; + list::iterator x; + + const std::set& automatable = r->what_can_be_automated (); + std::set has_visible_automation; + + r->what_has_visible_automation(has_visible_automation); + + if (automatable.empty()) { + return; + } + + for (x = redirect_automation.begin(); x != redirect_automation.end(); ++x) { + if ((*x)->redirect == r) { + break; + } + } + + if (x == redirect_automation.end()) { + + rai = new RedirectAutomationInfo (r); + redirect_automation.push_back (rai); + + } else { + + rai = *x; + + } + + /* any older menu was deleted at the top of redirects_changed() + when we cleared the subplugin menu. + */ + + rai->menu = manage (new Menu); + MenuList& items = rai->menu->items(); + rai->menu->set_name ("ArdourContextMenu"); + + items.clear (); + + for (std::set::const_iterator i = automatable.begin(); i != automatable.end(); ++i) { + + RedirectAutomationNode* ran; + CheckMenuItem* mitem; + + string name = r->describe_parameter (*i); + + items.push_back (CheckMenuElem (name)); + mitem = dynamic_cast (items.back()); + + if (has_visible_automation.find((*i)) != has_visible_automation.end()) { + mitem->set_active(true); + } + + if ((ran = find_redirect_automation_node (r, *i)) == 0) { + + /* new item */ + + ran = new RedirectAutomationNode (*i, mitem, *this); + + rai->lines.push_back (ran); + + } else { + + ran->menu_item = mitem; + + } + + mitem->toggled.connect (bind (slot (*this, &AudioTimeAxisView::redirect_menu_item_toggled), rai, ran)); + } + + /* add the menu for this redirect, because the subplugin + menu is always cleared at the top of redirects_changed(). + this is the result of some poor design in gtkmm and/or + GTK+. + */ + + subplugin_menu.items().push_back (MenuElem (r->name(), *rai->menu)); + rai->valid = true; +} + +void +AudioTimeAxisView::redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo* rai, + AudioTimeAxisView::RedirectAutomationNode* ran) +{ + bool showit = ran->menu_item->get_active(); + bool redraw = false; + + if (ran->view == 0 && showit) { + add_redirect_automation_curve (rai->redirect, ran->what); + redraw = true; + } + + if (showit != ran->view->marked_for_display()) { + + if (showit) { + ran->view->set_marked_for_display (true); + gtk_canvas_item_show (ran->view->canvas_display); + } else { + rai->redirect->mark_automation_visible (ran->what, true); + ran->view->set_marked_for_display (false); + ran->view->hide (); + } + + redraw = true; + + } + + if (redraw && !no_redraw) { + + /* now trigger a redisplay */ + + _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + + } +} + +void +AudioTimeAxisView::redirects_changed (void *src) +{ + using namespace Menu_Helpers; + + for (list::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { + (*i)->valid = false; + } + + subplugin_menu.items().clear (); + + _route.foreach_redirect (this, &AudioTimeAxisView::add_redirect_to_subplugin_menu); + _route.foreach_redirect (this, &AudioTimeAxisView::add_existing_redirect_automation_curves); + + for (list::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ) { + + list::iterator tmp; + + tmp = i; + ++tmp; + + if (!(*i)->valid) { + + delete *i; + redirect_automation.erase (i); + + } + + i = tmp; + } + + /* change in visibility was possible */ + + _route.gui_changed ("track_height", this); +} + +RedirectAutomationLine * +AudioTimeAxisView::find_redirect_automation_curve (Redirect *redirect, uint32_t what) +{ + RedirectAutomationNode* ran; + + if ((ran = find_redirect_automation_node (redirect, what)) != 0) { + if (ran->view) { + return dynamic_cast (ran->view->lines.front()); + } + } + + return 0; +} + +void +AudioTimeAxisView::show_all_automation () +{ + no_redraw = true; + + pan_automation_item->set_active (true); + gain_automation_item->set_active (true); + + for (list::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { + for (vector::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { + if ((*ii)->view == 0) { + add_redirect_automation_curve ((*i)->redirect, (*ii)->what); + } + + (*ii)->menu_item->set_active (true); + } + } + + no_redraw = false; + + _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ +} + +void +AudioTimeAxisView::show_existing_automation () +{ + no_redraw = true; + + pan_automation_item->set_active (true); + gain_automation_item->set_active (true); + + for (list::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { + for (vector::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { + if ((*ii)->view != 0) { + (*ii)->menu_item->set_active (true); + } + } + } + + no_redraw = false; + + _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ +} + +void +AudioTimeAxisView::hide_all_automation () +{ + no_redraw = true; + + pan_automation_item->set_active (false); + gain_automation_item->set_active (false); + + for (list::iterator i = redirect_automation.begin(); i != redirect_automation.end(); ++i) { + for (vector::iterator ii = (*i)->lines.begin(); ii != (*i)->lines.end(); ++ii) { + (*ii)->menu_item->set_active (false); + } + } + + no_redraw = false; + _route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ +} + +bool +AudioTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op) +{ + Playlist* what_we_got; + DiskStream* ds = get_diskstream(); + Playlist* playlist; + bool ret = false; + + if (ds == 0) { + /* route is a bus, not a track */ + return false; + } + + playlist = ds->playlist(); + + + TimeSelection time (selection.time); + float speed = ds->speed(); + if (speed != 1.0f) { + for (TimeSelection::iterator i = time.begin(); i != time.end(); ++i) { + (*i).start = (jack_nframes_t)floor( (float) (*i).start * speed); + (*i).end = (jack_nframes_t)floor( (float) (*i).end * speed); + } + } + + switch (op) { + case Cut: + _session.add_undo (playlist->get_memento()); + if ((what_we_got = playlist->cut (time)) != 0) { + editor.get_cut_buffer().add (what_we_got); + _session.add_redo_no_execute (playlist->get_memento()); + ret = true; + } + break; + case Copy: + if ((what_we_got = playlist->copy (time)) != 0) { + editor.get_cut_buffer().add (what_we_got); + } + break; + + case Clear: + _session.add_undo (playlist->get_memento()); + if ((what_we_got = playlist->cut (time)) != 0) { + _session.add_redo_no_execute (playlist->get_memento()); + what_we_got->unref (); + ret = true; + } + break; + } + + return ret; +} + +bool +AudioTimeAxisView::paste (jack_nframes_t pos, float times, Selection& selection, size_t nth) +{ + if (!is_audio_track()) { + return false; + } + + Playlist* playlist = get_diskstream()->playlist(); + PlaylistSelection::iterator p; + + for (p = selection.playlists.begin(); p != selection.playlists.end() && nth; ++p, --nth); + + if (p == selection.playlists.end()) { + return false; + } + + if (get_diskstream()->speed() != 1.0f) + pos = (jack_nframes_t) floor( (float) pos * get_diskstream()->speed() ); + + _session.add_undo (playlist->get_memento()); + playlist->paste (**p, pos, times); + _session.add_redo_no_execute (playlist->get_memento()); + + return true; +} + +void +AudioTimeAxisView::region_view_added (AudioRegionView* arv) +{ + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + AutomationTimeAxisView* atv; + + if ((atv = dynamic_cast (*i)) != 0) { + arv->add_ghost (*atv); + } + } +} + +void +AudioTimeAxisView::add_ghost_to_redirect (AudioRegionView* arv, AutomationTimeAxisView* atv) +{ + arv->add_ghost (*atv); +} + +list +AudioTimeAxisView::get_child_list() +{ + + listredirect_children; + + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + if (!(*i)->hidden()) { + redirect_children.push_back(*i); + } + } + return redirect_children; +} + + +void +AudioTimeAxisView::build_playlist_menu (Gtk::Menu * menu) +{ + using namespace Menu_Helpers; + + if (!menu || !is_audio_track()) { + return; + } + + MenuList& playlist_items = menu->items(); + menu->set_name ("ArdourContextMenu"); + playlist_items.clear(); + + if (playlist_menu) { + delete playlist_menu; + } + playlist_menu = new Menu; + playlist_menu->set_name ("ArdourContextMenu"); + + playlist_items.push_back (MenuElem (compose (_("Current: %1"), get_diskstream()->playlist()->name()))); + playlist_items.push_back (SeparatorElem()); + + playlist_items.push_back (MenuElem (_("Rename"), slot (*this, &AudioTimeAxisView::rename_current_playlist))); + playlist_items.push_back (SeparatorElem()); + + playlist_items.push_back (MenuElem (_("New"), slot (*this, &AudioTimeAxisView::use_new_playlist))); + playlist_items.push_back (MenuElem (_("New Copy"), slot(*this, &AudioTimeAxisView::use_copy_playlist))); + playlist_items.push_back (SeparatorElem()); + playlist_items.push_back (MenuElem (_("Clear Current"), slot (*this, &AudioTimeAxisView::clear_playlist))); + playlist_items.push_back (SeparatorElem()); + playlist_items.push_back (MenuElem(_("Select"), slot (*this, &AudioTimeAxisView::show_playlist_selector))); + +} + +void +AudioTimeAxisView::show_playlist_selector () +{ + editor.playlist_selector().show_for (this); +} + + +void +AudioTimeAxisView::map_frozen () +{ + if (!is_audio_track()) { + return; + } + + ENSURE_GUI_THREAD (slot (*this, &AudioTimeAxisView::map_frozen)); + + + switch (audio_track()->freeze_state()) { + case AudioTrack::Frozen: + playlist_button.set_sensitive (false); + rec_enable_button->set_sensitive (false); + break; + default: + playlist_button.set_sensitive (true); + rec_enable_button->set_sensitive (true); + break; + } +} + +void +AudioTimeAxisView::show_all_xfades () +{ + if (view) { + view->show_all_xfades (); + } +} + +void +AudioTimeAxisView::hide_all_xfades () +{ + if (view) { + view->hide_all_xfades (); + } +} + +void +AudioTimeAxisView::hide_dependent_views (TimeAxisViewItem& tavi) +{ + AudioRegionView* rv; + + if (view && (rv = dynamic_cast(&tavi)) != 0) { + view->hide_xfades_involving (*rv); + } +} + +void +AudioTimeAxisView::reveal_dependent_views (TimeAxisViewItem& tavi) +{ + AudioRegionView* rv; + + if (view && (rv = dynamic_cast(&tavi)) != 0) { + view->reveal_xfades_involving (*rv); + } +} + +void +AudioTimeAxisView::route_active_changed () +{ + RouteUI::route_active_changed (); + + if (is_audio_track()) { + if (_route.active()) { + controls_ebox.set_name ("AudioTrackControlsBaseUnselected"); + controls_base_selected_name = "AudioTrackControlsBaseSelected"; + controls_base_unselected_name = "AudioTrackControlsBaseUnselected"; + } else { + controls_ebox.set_name ("AudioTrackControlsBaseInactiveUnselected"); + controls_base_selected_name = "AudioTrackControlsBaseInactiveSelected"; + controls_base_unselected_name = "AudioTrackControlsBaseInactiveUnselected"; + } + } else { + if (_route.active()) { + controls_ebox.set_name ("BusControlsBaseUnselected"); + controls_base_selected_name = "BusControlsBaseSelected"; + controls_base_unselected_name = "BusControlsBaseUnselected"; + } else { + controls_ebox.set_name ("BusControlsBaseInactiveUnselected"); + controls_base_selected_name = "BusControlsBaseInactiveSelected"; + controls_base_unselected_name = "BusControlsBaseInactiveUnselected"; + } + } +} + +XMLNode* +AudioTimeAxisView::get_child_xml_node (std::string childname) +{ + return RouteUI::get_child_xml_node (childname); +} diff --git a/gtk2_ardour/audio_time_axis.h b/gtk2_ardour/audio_time_axis.h new file mode 100644 index 0000000000..678459072b --- /dev/null +++ b/gtk2_ardour/audio_time_axis.h @@ -0,0 +1,331 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_trackview_h__ +#define __ardour_trackview_h__ + +#include +#include +#include +#include +#include + +#include +#include + +#include "ardour_dialog.h" +#include "route_ui.h" +#include "enums.h" +#include "time_axis_view.h" + +namespace ALSA { + class MultiChannelDevice; +} + +namespace ARDOUR { + class Session; + class DiskStream; + class RouteGroup; + class Redirect; + class Insert; + class Location; + class AudioPlaylist; +} + +namespace LADSPA { + class Manager; + class Plugin; +} + +class PublicEditor; +class AudioThing; +class StreamView; +class Selection; +class Selectable; +class AudioRegionView; +class AutomationLine; +class AutomationGainLine; +class AutomationPanLine; +class RedirectAutomationLine; +class TimeSelection; +class AutomationTimeAxisView; + +class AudioTimeAxisView : public RouteUI, public TimeAxisView +{ + public: + AudioTimeAxisView (PublicEditor&, ARDOUR::Session&, ARDOUR::Route&, Gtk::Widget *canvas); + virtual ~AudioTimeAxisView (); + + void show_selection (TimeSelection&); + void automation_control_point_changed (ARDOUR::AutomationType); + + void set_samples_per_unit (double); + void set_height (TimeAxisView::TrackHeight); + void set_show_waveforms (bool yn); + void set_show_waveforms_recording (bool yn); + void show_timestretch (jack_nframes_t start, jack_nframes_t end); + void hide_timestretch (); + void selection_click (GdkEventButton*); + void set_selected_regionviews (AudioRegionSelection&); + void set_selected_points (PointSelection&); + void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list&); + void get_inverted_selectables (Selection&, list&); + void show_all_xfades (); + void hide_all_xfades (); + void hide_dependent_views (TimeAxisViewItem&); + void reveal_dependent_views (TimeAxisViewItem&); + + ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir); + + string name() const; + + ARDOUR::RouteGroup* edit_group() const; + + void build_playlist_menu (Gtk::Menu *); + ARDOUR::Playlist* playlist() const; + + /* overridden from parent to store display state */ + guint32 show_at (double y, int& nth, Gtk::VBox *parent); + void hide (); + + /* need accessors/mutators */ + + StreamView *view; + + /* editing operations */ + + bool cut_copy_clear (Selection&, Editing::CutCopyOp); + bool paste (jack_nframes_t, float times, Selection&, size_t nth); + + listget_child_list(); + + void set_state (const XMLNode&); + XMLNode* get_child_xml_node (std::string childname); + + private: + friend class StreamView; + friend class AudioRegionView; + + Gtk::Widget* parent_canvas; + + bool no_redraw; + + AutomationTimeAxisView *gain_track; + AutomationTimeAxisView *pan_track; + + void update_automation_view (ARDOUR::AutomationType); + void reset_redirect_automation_curves (); + + Gtk::HBox other_button_hbox; + + Gtk::Table button_table; + + Gtk::Button redirect_button; + Gtk::Button edit_group_button; + Gtk::Button playlist_button; + Gtk::Button size_button; + Gtk::Button automation_button; + Gtk::Button hide_button; + Gtk::Button visual_button; + + void route_active_changed (); + + void diskstream_changed (void *src); + void update_diskstream_display (); + + gint edit_click (GdkEventButton *); + + /* Redirect handling */ + + ArdourDialog redirect_window; + Gtk::CList redirect_display; + Gtk::Button redirect_add_button; + Gtk::Button redirect_remove_button; + Gtk::Button redirect_up_button; + Gtk::Button redirect_down_button; + Gtk::Button redirect_edit_button; + Gtk::HBox redirect_button_box; + Gtk::VBox redirect_vpacker; + Gtk::HBox redirect_display_hpacker; + + int redirect_selected_row; + + + // variables to get the context menu + // automation buttons correctly initialized + bool show_gain_automation; + bool show_pan_automation; + + void build_redirect_window (); + void redirect_click (); + void redirect_add (); + void redirect_remove (); + void redirect_edit (); + void redirect_relist (); + void redirect_row_selected (gint row, gint col, GdkEvent *ev); + void add_to_redirect_display (ARDOUR::Redirect *); + void redirects_changed (void *); + + SigC::Connection modified_connection; + SigC::Connection state_changed_connection; + + void take_name_changed (void *); + void route_name_changed (void *); + void name_entry_activated (); + void name_entry_changed (); + gint name_entry_focus_out_handler (GdkEventFocus*); + gint name_entry_key_release_handler (GdkEventKey*); + gint name_entry_button_release_handler (GdkEventButton*); + gint name_entry_button_press_handler (GdkEventButton*); + void on_area_realize (); + + virtual void label_view (); + + Gtk::Menu edit_group_menu; + Gtk::RadioMenuItem::Group edit_group_menu_radio_group; + + void add_edit_group_menu_item (ARDOUR::RouteGroup *); + void set_edit_group_from_menu (ARDOUR::RouteGroup *); + + void reset_samples_per_unit (); + + void select_track_color(); + + virtual void build_display_menu (); + + Gtk::CheckMenuItem* waveform_item; + Gtk::RadioMenuItem* traditional_item; + Gtk::RadioMenuItem* rectified_item; + + Gtk::RadioMenuItem* align_existing_item; + Gtk::RadioMenuItem* align_capture_item; + + void align_style_changed (); + void set_align_style (ARDOUR::AlignStyle); + + void toggle_show_waveforms (); + + void set_waveform_shape (WaveformShape); + void toggle_waveforms (); + + Gtk::Menu *playlist_menu; + Gtk::Menu *playlist_action_menu; + Gtk::MenuItem *playlist_item; + + /* playlist */ + + void set_playlist (ARDOUR::AudioPlaylist *); + void playlist_click (); + void show_playlist_selector (); + + void playlist_changed (); + void playlist_state_changed (ARDOUR::Change); + void playlist_modified (); + + void add_playlist_to_playlist_menu (ARDOUR::Playlist*); + void playlist_selected (ARDOUR::AudioPlaylist*); + void use_new_playlist (); + void use_copy_playlist (); + void clear_playlist (); + void rename_current_playlist (); + + /* automation stuff */ + + Gtk::Menu* automation_action_menu; + Gtk::CheckMenuItem* gain_automation_item; + Gtk::CheckMenuItem* pan_automation_item; + + void automation_click (); + void clear_automation (); + void hide_all_automation (); + void show_all_automation (); + void show_existing_automation (); + + struct RedirectAutomationNode { + uint32_t what; + Gtk::CheckMenuItem* menu_item; + AutomationTimeAxisView* view; + AudioTimeAxisView& parent; + + RedirectAutomationNode (uint32_t w, Gtk::CheckMenuItem* mitem, AudioTimeAxisView& p) + : what (w), menu_item (mitem), view (0), parent (p) {} + + ~RedirectAutomationNode (); + }; + + struct RedirectAutomationInfo { + ARDOUR::Redirect* redirect; + bool valid; + Gtk::Menu* menu; + vector lines; + + RedirectAutomationInfo (ARDOUR::Redirect* r) + : redirect (r), valid (true) {} + + ~RedirectAutomationInfo (); + }; + + list redirect_automation; + RedirectAutomationNode* find_redirect_automation_node (ARDOUR::Redirect *redirect, uint32_t what); + + Gtk::Menu subplugin_menu; + void add_redirect_to_subplugin_menu (ARDOUR::Redirect *); + + void remove_ran (RedirectAutomationNode* ran); + + void redirect_menu_item_toggled (AudioTimeAxisView::RedirectAutomationInfo*, + AudioTimeAxisView::RedirectAutomationNode*); + void redirect_automation_track_hidden (RedirectAutomationNode*, ARDOUR::Redirect*); + + vector redirect_automation_curves; + RedirectAutomationLine *find_redirect_automation_curve (ARDOUR::Redirect*,uint32_t); + void add_redirect_automation_curve (ARDOUR::Redirect*, uint32_t); + void add_existing_redirect_automation_curves (ARDOUR::Redirect*); + + GtkCanvasItem *timestretch_rect; + + void timestretch (jack_nframes_t start, jack_nframes_t end); + + void visual_click (); + void hide_click (); + gint when_displayed (GdkEventAny*); + + void speed_changed (); + + void add_gain_automation_child (); + void add_pan_automation_child (); + void add_parameter_automation_child (); + + void toggle_gain_track (); + void toggle_pan_track (); + + void gain_hidden (); + void pan_hidden (); + + void update_pans (); + + void region_view_added (AudioRegionView*); + void add_ghost_to_redirect (AudioRegionView*, AutomationTimeAxisView*); + + void map_frozen (); +}; + +#endif /* __ardour_trackview_h__ */ + diff --git a/gtk2_ardour/automation_gain_line.cc b/gtk2_ardour/automation_gain_line.cc new file mode 100644 index 0000000000..8331d983d7 --- /dev/null +++ b/gtk2_ardour/automation_gain_line.cc @@ -0,0 +1,60 @@ +/* + Copyright (C) 2000-2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include +#include + +#include "public_editor.h" +#include "automation_gain_line.h" +#include "utils.h" + +#include + +using namespace std; +using namespace ARDOUR; + +AutomationGainLine::AutomationGainLine (string name, Session& s, TimeAxisView& tv, GtkCanvasItem* parent, + Curve& c, + gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer), + gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer)) + : AutomationLine (name, tv, parent, c, point_callback, line_callback), + session (s) +{ + set_verbose_cursor_uses_gain_mapping (true); +} + +void +AutomationGainLine::view_to_model_y (double& y) +{ + y = slider_position_to_gain (y); + y = max (0.0, y); + y = min (2.0, y); +} + +void +AutomationGainLine::model_to_view_y (double& y) +{ + y = gain_to_slider_position (y); +} + + + diff --git a/gtk2_ardour/automation_gain_line.h b/gtk2_ardour/automation_gain_line.h new file mode 100644 index 0000000000..058576336a --- /dev/null +++ b/gtk2_ardour/automation_gain_line.h @@ -0,0 +1,36 @@ +#ifndef __ardour_gtk_automation_gain_line_h__ +#define __ardour_gtk_automation_gain_line_h__ + +#include +#include +#include + +#include "automation_line.h" + +namespace ARDOUR { + class Session; +} + + +class TimeAxisView; + +class AutomationGainLine : public AutomationLine +{ + public: + AutomationGainLine (string name, ARDOUR::Session&, TimeAxisView&, GtkCanvasItem* parent, + ARDOUR::Curve&, + gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer), + gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer)); + + void view_to_model_y (double&); + void model_to_view_y (double&); + + private: + ARDOUR::Session& session; + +}; + + +#endif /* __ardour_gtk_automation_gain_line_h__ */ + + diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc new file mode 100644 index 0000000000..1b9309e7e0 --- /dev/null +++ b/gtk2_ardour/automation_line.cc @@ -0,0 +1,1293 @@ +/* + Copyright (C) 2002-2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include + +#include +#include +#include + +#include "canvas-simplerect.h" +#include "automation_line.h" +#include "rgb_macros.h" +#include "ardour_ui.h" +#include "public_editor.h" +#include "utils.h" +#include "selection.h" +#include "time_axis_view.h" +#include "point_selection.h" +#include "automation_selectable.h" +#include "automation_time_axis.h" +#include "public_editor.h" + +#include + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; +using namespace Editing; + +ControlPoint::ControlPoint (AutomationLine& al, gint (*event_handler)(GtkCanvasItem*, GdkEvent*, gpointer)) + : line (al) +{ + model = al.the_list().end(); + view_index = 0; + can_slide = true; + _x = 0; + _y = 0; + _shape = Full; + _size = 4.0; + selected = false; + + item = gtk_canvas_item_new (line.canvas_group(), + gtk_canvas_simplerect_get_type(), + "draw", (gboolean) TRUE, + "fill", (gboolean) FALSE, + "fill_color_rgba", color_map[cControlPointFill], + "outline_color_rgba", color_map[cControlPointOutline], + "outline_pixels", (gint) 1, + NULL); + + gtk_object_set_data (GTK_OBJECT(item), "control_point", this); + gtk_signal_connect (GTK_OBJECT(item), "event", (GtkSignalFunc) event_handler, this); + + hide (); + set_visible (false); +} + +ControlPoint::ControlPoint (const ControlPoint& other, bool dummy_arg_to_force_special_copy_constructor) + : line (other.line) +{ + if (&other == this) { + return; + } + + model = other.model; + view_index = other.view_index; + can_slide = other.can_slide; + _x = other._x; + _y = other._y; + _shape = other._shape; + _size = other._size; + selected = false; + + item = gtk_canvas_item_new (line.canvas_group(), + gtk_canvas_simplerect_get_type(), + "fill", (gboolean) FALSE, + "outline_color_rgba", color_map[cEnteredControlPointOutline], + "outline_pixels", (gint) 1, + NULL); + + /* NOTE: no event handling in copied ControlPoints */ + + hide (); + set_visible (false); +} + +ControlPoint::~ControlPoint () +{ + gtk_object_destroy (GTK_OBJECT(item)); +} + +void +ControlPoint::hide () +{ + gtk_canvas_item_hide (item); +} + +void +ControlPoint::show() +{ + gtk_canvas_item_show (item); +} + +void +ControlPoint::set_visible (bool yn) +{ + gtk_canvas_item_set (item, "draw", (gboolean) yn, NULL); +} + +void +ControlPoint::reset (double x, double y, AutomationList::iterator mi, uint32_t vi, ShapeType shape) +{ + model = mi; + view_index = vi; + move_to (x, y, shape); +} + +void +ControlPoint::show_color (bool entered, bool hide_too) +{ + if (entered) { + if (selected) { + gtk_canvas_item_set (item, "outline_color_rgba", color_map[cEnteredControlPointSelected], NULL); + set_visible(true); + } else { + gtk_canvas_item_set (item, "outline_color_rgba", color_map[cEnteredControlPoint], NULL); + if (hide_too) { + set_visible(false); + } + } + + } else { + if (selected) { + gtk_canvas_item_set (item, "outline_color_rgba", color_map[cControlPointSelected], NULL); + set_visible(true); + } else { + gtk_canvas_item_set (item, "outline_color_rgba", color_map[cControlPoint], NULL); + if (hide_too) { + set_visible(false); + } + } + } +} + +void +ControlPoint::set_size (double sz) +{ + _size = sz; + +#if 0 + if (_size > 6.0) { + gtk_canvas_item_set (item, + "fill", (gboolean) TRUE, + NULL); + } else { + gtk_canvas_item_set (item, + "fill", (gboolean) FALSE, + NULL); + } +#endif + + move_to (_x, _y, _shape); +} + +void +ControlPoint::move_to (double x, double y, ShapeType shape) +{ + double x1 = 0; + double x2 = 0; + double half_size = rint(_size/2.0); + + switch (shape) { + case Full: + x1 = x - half_size; + x2 = x + half_size; + break; + case Start: + x1 = x; + x2 = x + half_size; + break; + case End: + x1 = x - half_size; + x2 = x; + break; + } + + gtk_canvas_item_set (item, + "x1", x1, + "x2", x2, + "y1", y - half_size, + "y2", y + half_size, + NULL); + + _x = x; + _y = y; + _shape = shape; +} + +/*****/ + +AutomationLine::AutomationLine (string name, TimeAxisView& tv, GtkCanvasItem* parent, AutomationList& al, + gint (*point_handler)(GtkCanvasItem*, GdkEvent*, gpointer), + gint (*line_handler)(GtkCanvasItem*, GdkEvent*, gpointer)) + : trackview (tv), + _name (name), + alist (al) +{ + point_coords = 0; + points_visible = false; + update_pending = false; + _vc_uses_gain_mapping = false; + no_draw = false; + _visible = true; + point_callback = point_handler; + _parent_group = parent; + terminal_points_can_slide = true; + _height = 0; + + group = gtk_canvas_item_new (GTK_CANVAS_GROUP(parent), + gtk_canvas_group_get_type(), + "x", 0.0, + "y", 0.0, + NULL); + + line = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_line_get_type(), + "width_pixels", (guint) 1, + NULL); + + // cerr << _name << " line @ " << line << endl; + + gtk_object_set_data (GTK_OBJECT(line), "line", this); + gtk_signal_connect (GTK_OBJECT(line), "event", (GtkSignalFunc) line_handler, this); + + alist.StateChanged.connect (slot (*this, &AutomationLine::list_changed)); +} + +AutomationLine::~AutomationLine () +{ + if (point_coords) { + gtk_canvas_points_unref (point_coords); + } + + vector_delete (&control_points); + + gtk_object_destroy (GTK_OBJECT(group)); +} + +void +AutomationLine::queue_reset () +{ + if (!update_pending) { + update_pending = true; + Gtkmmext::UI::instance()->call_slot (slot (*this, &AutomationLine::reset)); + } +} + +void +AutomationLine::set_point_size (double sz) +{ + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + (*i)->set_size (sz); + } +} + +void +AutomationLine::show () +{ + gtk_canvas_item_show (line); + + if (points_visible) { + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + (*i)->show (); + } + } + + _visible = true; +} + +void +AutomationLine::hide () +{ + gtk_canvas_item_hide (line); + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + (*i)->hide(); + } + _visible = false; +} + +void +AutomationLine::set_height (guint32 h) +{ + if (h != _height) { + _height = h; + + if (_height > (guint32) TimeAxisView::Larger) { + set_point_size (8.0); + } else if (_height > (guint32) TimeAxisView::Normal) { + set_point_size (6.0); + } else { + set_point_size (4.0); + } + + reset (); + } +} + +void +AutomationLine::set_line_color (uint32_t color) +{ + _line_color = color; + gtk_canvas_item_set (line, "fill_color_rgba", color, NULL); +} + +void +AutomationLine::set_verbose_cursor_uses_gain_mapping (bool yn) +{ + if (yn != _vc_uses_gain_mapping) { + _vc_uses_gain_mapping = yn; + reset (); + } +} + +ControlPoint* +AutomationLine::nth (uint32_t n) +{ + if (n < control_points.size()) { + return control_points[n]; + } else { + return 0; + } +} + +void +AutomationLine::modify_view (ControlPoint& cp, double x, double y, bool with_push) +{ + modify_view_point (cp, x, y, with_push); + update_line (); +} + +void +AutomationLine::modify_view_point (ControlPoint& cp, double x, double y, bool with_push) +{ + double delta = 0.0; + uint32_t last_movable = UINT_MAX; + double x_limit = DBL_MAX; + + /* this just changes the current view. it does not alter + the model in any way at all. + */ + + /* clamp y-coord appropriately. y is supposed to be a normalized fraction (0.0-1.0), + and needs to be converted to a canvas unit distance. + */ + + y = max (0.0, y); + y = min (1.0, y); + y = _height - (y * _height); + + if (cp.can_slide) { + + /* x-coord cannot move beyond adjacent points or the start/end, and is + already in frames. it needs to be converted to canvas units. + */ + + x = trackview.editor.frame_to_unit (x); + + /* clamp x position using view coordinates */ + + ControlPoint *before; + ControlPoint *after; + + if (cp.view_index) { + before = nth (cp.view_index - 1); + x = max (x, before->get_x()+1.0); + } else { + before = &cp; + } + + + if (!with_push) { + if (cp.view_index < control_points.size() - 1) { + + after = nth (cp.view_index + 1); + + /*if it is a "spike" leave the x alone */ + + if (after->get_x() - before->get_x() < 2) { + x = cp.get_x(); + + } else { + x = min (x, after->get_x()-1.0); + } + } else { + after = &cp; + } + + } else { + + ControlPoint* after; + + /* find the first point that can't move */ + + for (uint32_t n = cp.view_index + 1; (after = nth (n)) != 0; ++n) { + if (!after->can_slide) { + x_limit = after->get_x() - 1.0; + last_movable = after->view_index; + break; + } + } + + delta = x - cp.get_x(); + } + + } else { + + /* leave the x-coordinate alone */ + + x = trackview.editor.frame_to_unit ((*cp.model)->when); + + } + + if (!with_push) { + + cp.move_to (x, y, ControlPoint::Full); + reset_line_coords (cp); + + } else { + + uint32_t limit = min (control_points.size(), (size_t)last_movable); + + /* move the current point to wherever the user told it to go, subject + to x_limit. + */ + + cp.move_to (min (x, x_limit), y, ControlPoint::Full); + reset_line_coords (cp); + + /* now move all subsequent control points, to reflect the motion. + */ + + for (uint32_t i = cp.view_index + 1; i < limit; ++i) { + ControlPoint *p = nth (i); + double new_x; + + if (p->can_slide) { + new_x = min (p->get_x() + delta, x_limit); + p->move_to (new_x, p->get_y(), ControlPoint::Full); + reset_line_coords (*p); + } + } + } +} + +void +AutomationLine::reset_line_coords (ControlPoint& cp) +{ + if (point_coords) { + point_coords->coords[cp.view_index*2] = cp.get_x(); + point_coords->coords[(cp.view_index*2) + 1] = cp.get_y(); + } +} + +void +AutomationLine::update_line () +{ + gtk_canvas_item_set (line, "points", point_coords, NULL); +} + +void +AutomationLine::sync_model_with_view_line (uint32_t start, uint32_t end) +{ + + ControlPoint *p; + + update_pending = true; + + for (uint32_t i = start; i <= end; ++i) { + p = nth(i); + sync_model_with_view_point(*p); + } + + +} + +void +AutomationLine::model_representation (ControlPoint& cp, ModelRepresentation& mr) +{ + /* part one: find out where the visual control point is. + initial results are in canvas units. ask the + line to convert them to something relevant. + */ + + mr.xval = (jack_nframes_t) floor (cp.get_x()); + mr.yval = 1.0 - (cp.get_y() / _height); + + + /* if xval has not changed, set it directly from the model to avoid rounding errors */ + + if (mr.xval == trackview.editor.frame_to_unit((*cp.model)->when)) { + mr.xval = (jack_nframes_t) (*cp.model)->when; + } else { + mr.xval = trackview.editor.unit_to_frame (mr.xval); + } + + + /* virtual call: this will do the right thing + for whatever particular type of line we are. + */ + + view_to_model_y (mr.yval); + + /* part 2: find out where the model point is now + */ + + mr.xpos = (jack_nframes_t) (*cp.model)->when; + mr.ypos = (*cp.model)->value; + + /* part 3: get the position of the visual control + points before and after us. + */ + + ControlPoint* before; + ControlPoint* after; + + if (cp.view_index) { + before = nth (cp.view_index - 1); + } else { + before = 0; + } + + after = nth (cp.view_index + 1); + + if (before) { + mr.xmin = (jack_nframes_t) (*before->model)->when; + mr.ymin = (*before->model)->value; + mr.start = before->model; + ++mr.start; + } else { + mr.xmin = mr.xpos; + mr.ymin = mr.ypos; + mr.start = cp.model; + } + + if (after) { + mr.end = after->model; + } else { + mr.xmax = mr.xpos; + mr.ymax = mr.ypos; + mr.end = cp.model; + ++mr.end; + } +} + +void +AutomationLine::sync_model_from (ControlPoint& cp) +{ + ControlPoint* p; + uint32_t lasti; + + sync_model_with_view_point (cp); + + /* we might have moved all points after `cp' by some amount + if we pressed the with_push modifyer some of the time during the drag + so all subsequent points have to be resynced + */ + + lasti = control_points.size() - 1; + p = nth (lasti); + + update_pending = true; + + while (p != &cp && lasti) { + sync_model_with_view_point (*p); + --lasti; + p = nth (lasti); + } +} + +void +AutomationLine::sync_model_with_view_point (ControlPoint& cp) +{ + ModelRepresentation mr; + double ydelta; + + model_representation (cp, mr); + + /* part 4: how much are we changing the central point by */ + + ydelta = mr.yval - mr.ypos; + + /* IMPORTANT: changing the model when the x-coordinate changes + may invalidate the iterators that we are using. this means that we have + to change the points before+after the one corresponding to the visual CP + first (their x-coordinate doesn't change). then we change the + "main" point. + + apply the full change to the central point, and interpolate + in each direction to cover all model points represented + by the control point. + */ + + /* part 5: change all points before the primary point */ + + for (AutomationList::iterator i = mr.start; i != cp.model; ++i) { + + double delta; + + delta = ydelta * ((*i)->when - mr.xmin) / (mr.xpos - mr.xmin); + + /* x-coordinate (generally time) stays where it is, + y-coordinate moves by a certain amount. + */ + + update_pending = true; + change_model (i, (*i)->when, mr.yval + delta); + } + + /* part 6: change later points */ + + AutomationList::iterator i = cp.model; + + ++i; + + while (i != mr.end) { + + double delta; + + delta = ydelta * (mr.xmax - (*i)->when) / (mr.xmax - mr.xpos); + + /* x-coordinate (generally time) stays where it is, + y-coordinate moves by a certain amount. + */ + + update_pending = true; + change_model (i, (*i)->when, (*i)->value + delta); + + ++i; + } + + /* part 7: change the primary point */ + + update_pending = true; + change_model (cp.model, mr.xval, mr.yval); +} + +void +AutomationLine::determine_visible_control_points (GtkCanvasPoints* points) +{ + uint32_t xi, yi, view_index, pi; + int n; + AutomationList::iterator model; + uint32_t npoints = points->num_points; + double last_control_point_x = 0.0; + double last_control_point_y = 0.0; + uint32_t this_rx = 0; + uint32_t prev_rx = 0; + uint32_t this_ry = 0; + uint32_t prev_ry = 0; + double* slope; + + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + (*i)->hide(); + } + gtk_canvas_item_hide (line); + + if (points == 0 || points->num_points == 0) { + return; + } + + /* compute derivative/slope for the entire line */ + + slope = new double[npoints]; + + for (n = 0, xi = 2, yi = 3, view_index = 0; n < points->num_points - 1; xi += 2, yi +=2, ++n, ++view_index) { + double xdelta; + double ydelta; + xdelta = points->coords[xi] - points->coords[xi-2]; + ydelta = points->coords[yi] - points->coords[yi-2]; + slope[view_index] = ydelta/xdelta; + } + + /* read all points and decide which ones to show as control points */ + + for (model = alist.begin(), pi = 0, xi = 0, yi = 1, view_index = 0; pi < npoints; ++model, xi += 2, yi +=2, ++pi) { + + /* now ensure that the control_points vector reflects the current curve + state, but don't plot control points too close together. also, don't + plot a series of points all with the same value. + + always plot the first and last points, of course. + */ + + if (invalid_point (points, pi)) { + /* for some reason, we are supposed to ignore this point, + but still keep track of the model index. + */ + continue; + } + + if (pi > 0 && pi < npoints - 1) { + if (slope[pi] == slope[pi-1]) { + + /* no reason to display this point */ + + continue; + } + } + + /* need to round here. the ultimate coordinates are integer + pixels, so tiny deltas in the coords will be eliminated + and we end up with "colinear" line segments. since the + line rendering code in libart doesn't like this very + much, we eliminate them here. don't do this for the first and last + points. + */ + + this_rx = (uint32_t) rint (points->coords[xi]); + this_ry = (unsigned long) rint (points->coords[yi]); + + if (view_index && pi != npoints && (this_rx == prev_rx) && (this_ry == prev_ry)) { + + continue; + } + + /* ok, we should display this point */ + + if (view_index >= control_points.size()) { + /* make sure we have enough control points */ + + ControlPoint* ncp = new ControlPoint (*this, point_callback); + + if (_height > (guint32) TimeAxisView::Larger) { + ncp->set_size (8.0); + } else if (_height > (guint32) TimeAxisView::Normal) { + ncp->set_size (6.0); + } else { + ncp->set_size (4.0); + } + + control_points.push_back (ncp); + } + + ControlPoint::ShapeType shape; + + if (!terminal_points_can_slide) { + if (pi == 0) { + control_points[view_index]->can_slide = false; + if (points->coords[xi] == 0) { + shape = ControlPoint::Start; + } else { + shape = ControlPoint::Full; + } + } else if (pi == npoints - 1) { + control_points[view_index]->can_slide = false; + shape = ControlPoint::End; + } else { + control_points[view_index]->can_slide = true; + shape = ControlPoint::Full; + } + } else { + control_points[view_index]->can_slide = true; + shape = ControlPoint::Full; + } + + control_points[view_index]->reset (points->coords[xi], points->coords[yi], model, view_index, shape); + + last_control_point_x = points->coords[xi]; + last_control_point_y = points->coords[yi]; + + prev_rx = this_rx; + prev_ry = this_ry; + + /* finally, control visibility */ + + if (_visible && points_visible) { + control_points[view_index]->show (); + control_points[view_index]->set_visible (true); + } else { + if (!points_visible) { + control_points[view_index]->set_visible (false); + } + } + + view_index++; + } + + /* discard extra CP's to avoid confusing ourselves */ + + while (control_points.size() > view_index) { + ControlPoint* cp = control_points.back(); + control_points.pop_back (); + delete cp; + } + + if (!terminal_points_can_slide) { + control_points.back()->can_slide = false; + } + + delete [] slope; + + /* Now make sure the "point_coords" array is large enough + to represent all the visible points. + */ + + if (view_index > 1) { + + npoints = view_index; + + if (point_coords) { + if (point_coords->num_points < (int) npoints) { + gtk_canvas_points_unref (point_coords); + point_coords = get_canvas_points ("autoline", npoints); + } else { + point_coords->num_points = npoints; + } + } else { + point_coords = get_canvas_points ("autoline", npoints); + } + + /* reset the line coordinates */ + + uint32_t pci; + + for (pci = 0, view_index = 0; view_index < npoints; ++view_index) { + point_coords->coords[pci++] = control_points[view_index]->get_x(); + point_coords->coords[pci++] = control_points[view_index]->get_y(); + } + + // cerr << "set al2 points, nc = " << point_coords->num_points << endl; + gtk_canvas_item_set (line, "points", point_coords, NULL); + + if (_visible) { + gtk_canvas_item_show (line); + } + } + + set_selected_points (trackview.editor.get_selection().points); +} + +string +AutomationLine::get_verbose_cursor_string (float fraction) +{ + char buf[32]; + + if (_vc_uses_gain_mapping) { + if (fraction == 0.0) { + snprintf (buf, sizeof (buf), "-inf dB"); + } else { + snprintf (buf, sizeof (buf), "%.1fdB", coefficient_to_dB (slider_position_to_gain (fraction))); + } + } else { + snprintf (buf, sizeof (buf), "%.2f", fraction); + } + + return buf; +} + +bool +AutomationLine::invalid_point (GtkCanvasPoints* p, uint32_t index) +{ + return p->coords[index*2] == max_frames && p->coords[(index*2)+1] == DBL_MAX; +} + +void +AutomationLine::invalidate_point (GtkCanvasPoints* p, uint32_t index) +{ + p->coords[index*2] = max_frames; + p->coords[(index*2)+1] = DBL_MAX; +} + +void +AutomationLine::start_drag (ControlPoint* cp, float fraction) +{ + if (trackview.editor.current_session() == 0) { /* how? */ + return; + } + + string str; + + if (cp) { + str = _("automation event move"); + } else { + str = _("automation range drag"); + } + + trackview.editor.current_session()->begin_reversible_command (str); + trackview.editor.current_session()->add_undo (get_memento()); + + first_drag_fraction = fraction; + last_drag_fraction = fraction; + drags = 0; +} + +void +AutomationLine::point_drag (ControlPoint& cp, jack_nframes_t x, float fraction, bool with_push) +{ + modify_view (cp, x, fraction, with_push); + drags++; +} + +void +AutomationLine::line_drag (uint32_t i1, uint32_t i2, float fraction, bool with_push) +{ + double ydelta = fraction - last_drag_fraction; + + last_drag_fraction = fraction; + + line_drag_cp1 = i1; + line_drag_cp2 = i2; + + ControlPoint *cp; + + for (uint32_t i = i1 ; i <= i2; i++) { + cp = nth (i); + modify_view_point (*cp, trackview.editor.unit_to_frame (cp->get_x()), ((_height - cp->get_y()) /_height) + ydelta, with_push); + } + + update_line (); + + drags++; +} + +void +AutomationLine::end_drag (ControlPoint* cp) +{ + if (drags) { + + if (cp) { + sync_model_from (*cp); + } else { + sync_model_with_view_line (line_drag_cp1, line_drag_cp2); + } + + update_pending = false; + + trackview.editor.current_session()->add_redo_no_execute (get_memento()); + trackview.editor.current_session()->commit_reversible_command (); + trackview.editor.current_session()->set_dirty (); + } +} + +bool +AutomationLine::control_points_adjacent (double xval, uint32_t & before, uint32_t& after) +{ + ControlPoint *bcp = 0; + ControlPoint *acp = 0; + double unit_xval; + + /* xval is in frames */ + + unit_xval = trackview.editor.frame_to_unit (xval); + + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + + if ((*i)->get_x() <= unit_xval) { + + if (!bcp || (*i)->get_x() > bcp->get_x()) { + bcp = *i; + before = bcp->view_index; + } + + } else if ((*i)->get_x() > unit_xval) { + acp = *i; + after = acp->view_index; + break; + } + } + + return bcp && acp; +} + +bool +AutomationLine::is_last_point (ControlPoint& cp) +{ + ModelRepresentation mr; + + model_representation (cp, mr); + + // If the list is not empty, and the point is the last point in the list + + if (!alist.empty() && mr.end == alist.end()) { + return true; + } + + return false; +} + +bool +AutomationLine::is_first_point (ControlPoint& cp) +{ + ModelRepresentation mr; + + model_representation (cp, mr); + + // If the list is not empty, and the point is the first point in the list + + if (!alist.empty() && mr.start == alist.begin()) { + return true; + } + + return false; +} + +// This is copied into AudioRegionGainLine +void +AutomationLine::remove_point (ControlPoint& cp) +{ + ModelRepresentation mr; + + model_representation (cp, mr); + + trackview.editor.current_session()->begin_reversible_command (_("remove control point")); + trackview.editor.current_session()->add_undo (get_memento()); + + alist.erase (mr.start, mr.end); + + trackview.editor.current_session()->add_redo_no_execute (get_memento()); + trackview.editor.current_session()->commit_reversible_command (); + trackview.editor.current_session()->set_dirty (); +} + +void +AutomationLine::get_selectables (jack_nframes_t& start, jack_nframes_t& end, + double botfrac, double topfrac, list& results) +{ + + double top; + double bot; + jack_nframes_t nstart; + jack_nframes_t nend; + bool collecting = false; + + /* Curse X11 and its inverted coordinate system! */ + + bot = (1.0 - topfrac) * _height; + top = (1.0 - botfrac) * _height; + + nstart = max_frames; + nend = 0; + + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + + jack_nframes_t when = (jack_nframes_t) (*(*i)->model)->when; + + if (when >= start && when <= end) { + + if ((*i)->get_y() >= bot && (*i)->get_y() <= top) { + + (*i)->show(); + (*i)->set_visible(true); + collecting = true; + nstart = min (nstart, when); + nend = max (nend, when); + + } else { + + if (collecting) { + + results.push_back (new AutomationSelectable (nstart, nend, botfrac, topfrac, trackview)); + collecting = false; + nstart = max_frames; + nend = 0; + } + } + } + } + + if (collecting) { + results.push_back (new AutomationSelectable (nstart, nend, botfrac, topfrac, trackview)); + } + +} + +void +AutomationLine::get_inverted_selectables (Selection&, list& results) +{ + // hmmm .... +} + +void +AutomationLine::set_selected_points (PointSelection& points) +{ + double top; + double bot; + + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + (*i)->selected = false; + } + + if (points.empty()) { + goto out; + } + + for (PointSelection::iterator r = points.begin(); r != points.end(); ++r) { + + if (&(*r).track != &trackview) { + continue; + } + + /* Curse X11 and its inverted coordinate system! */ + + bot = (1.0 - (*r).high_fract) * _height; + top = (1.0 - (*r).low_fract) * _height; + + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + + double rstart, rend; + + rstart = trackview.editor.frame_to_unit ((*r).start); + rend = trackview.editor.frame_to_unit ((*r).end); + + if ((*i)->get_x() >= rstart && (*i)->get_x() <= rend) { + + if ((*i)->get_y() >= bot && (*i)->get_y() <= top) { + + (*i)->selected = true; + } + } + + } + } + + out: + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + (*i)->show_color (false, !points_visible); + } + +} + +void +AutomationLine::show_selection () +{ + TimeSelection& time (trackview.editor.get_selection().time); + + // cerr << "show selection\n"; + + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + + (*i)->selected = false; + + for (list::iterator r = time.begin(); r != time.end(); ++r) { + double rstart, rend; + + rstart = trackview.editor.frame_to_unit ((*r).start); + rend = trackview.editor.frame_to_unit ((*r).end); + + if ((*i)->get_x() >= rstart && (*i)->get_x() <= rend) { + (*i)->selected = true; + break; + } + } + + (*i)->show_color (false, !points_visible); + } +} + +void +AutomationLine::hide_selection () +{ + // cerr << "hide selection\n"; +// show_selection (); +} + + +// This is copied into AudioRegionGainLine +UndoAction +AutomationLine::get_memento () +{ + return alist.get_memento(); +} + +void +AutomationLine::list_changed (Change ignored) +{ + queue_reset (); +} + +void +AutomationLine::reset_callback (const AutomationList& events) +{ + GtkCanvasPoints *tmp_points; + uint32_t npoints = events.size(); + + if (npoints == 0) { + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + delete *i; + } + control_points.clear (); + gtk_canvas_item_hide (line); + return; + } + + tmp_points = get_canvas_points ("autoline reset", max (npoints, (uint32_t) 2)); + + uint32_t xi, yi; + AutomationList::const_iterator ai; + + for (ai = events.const_begin(), xi = 0, yi = 1; ai != events.const_end(); xi += 2, yi +=2, ++ai) { + + tmp_points->coords[xi] = trackview.editor.frame_to_unit ((*ai)->when); + double translated_y; + + translated_y = (*ai)->value; + model_to_view_y (translated_y); + tmp_points->coords[yi] = _height - (translated_y * _height); + } + + tmp_points->num_points = npoints; + + determine_visible_control_points (tmp_points); + gtk_canvas_points_unref (tmp_points); +} + +void +AutomationLine::reset () +{ + update_pending = false; + + if (no_draw) { + return; + } + + alist.apply_to_points (*this, &AutomationLine::reset_callback); +} + +void +AutomationLine::clear () +{ + /* parent must create command */ + trackview.editor.current_session()->add_undo (get_memento()); + alist.clear(); + trackview.editor.current_session()->add_redo_no_execute (get_memento()); + trackview.editor.current_session()->commit_reversible_command (); + trackview.editor.current_session()->set_dirty (); +} + +void +AutomationLine::change_model (AutomationList::iterator i, double x, double y) +{ + alist.modify (i, (jack_nframes_t) x, y); +} + +void +AutomationLine::change_model_range (AutomationList::iterator start, AutomationList::iterator end, double xdelta, float ydelta) +{ + alist.move_range (start, end, xdelta, ydelta); +} + +void +AutomationLine::show_all_control_points () +{ + points_visible = true; + + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + (*i)->show (); + (*i)->set_visible (true); + } +} + +void +AutomationLine::hide_all_but_selected_control_points () +{ + points_visible = false; + + for (vector::iterator i = control_points.begin(); i != control_points.end(); ++i) { + if (!(*i)->selected) { + (*i)->set_visible (false); + } + } +} diff --git a/gtk2_ardour/automation_line.h b/gtk2_ardour/automation_line.h new file mode 100644 index 0000000000..ab3cc2bb43 --- /dev/null +++ b/gtk2_ardour/automation_line.h @@ -0,0 +1,223 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_automation_line_h__ +#define __ardour_automation_line_h__ + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include + +using std::vector; +using std::string; + +class AutomationLine; +class ControlPoint; +class PointSelection; +class TimeAxisView; +class AutomationTimeAxisView; +class Selectable; +class Selection; + +class ControlPoint +{ + public: + ControlPoint (AutomationLine& al, gint (*event_handler)(GtkCanvasItem*, GdkEvent*, gpointer)); + ControlPoint (const ControlPoint&, bool dummy_arg_to_force_special_copy_constructor); + ~ControlPoint (); + + enum ShapeType { + Full, + Start, + End + }; + + void move_to (double x, double y, ShapeType); + void reset (double x, double y, ARDOUR::AutomationList::iterator, uint32_t, ShapeType); + double get_x() const { return _x; } + double get_y() const { return _y; } + + void hide (); + void show (); + void show_color (bool entered, bool hide_too); + + void set_size (double); + void set_visible (bool); + + GtkCanvasItem* item; + AutomationLine& line; + uint32_t view_index; + ARDOUR::AutomationList::iterator model; + bool can_slide; + bool selected; + + private: + double _x; + double _y; + double _size; + ShapeType _shape; +}; + +class AutomationLine : public SigC::Object +{ + public: + AutomationLine (string name, TimeAxisView&, GtkCanvasItem *, ARDOUR::AutomationList&, + gint (*point_event_handler)(GtkCanvasItem*, GdkEvent*, gpointer), + gint (*line_event_handler)(GtkCanvasItem*, GdkEvent*, gpointer)); + + virtual ~AutomationLine (); + + void queue_reset (); + void reset (); + void clear(); + + void set_selected_points (PointSelection&); + void get_selectables (jack_nframes_t& start, jack_nframes_t& end, + double botfrac, double topfrac, + list& results); + void get_inverted_selectables (Selection&, list& results); + + virtual void remove_point (ControlPoint&); + bool control_points_adjacent (double xval, uint32_t& before, uint32_t& after); + + /* dragging API */ + + virtual void start_drag (ControlPoint*, float fraction); + virtual void point_drag(ControlPoint&, jack_nframes_t x, float, bool with_push); + virtual void end_drag (ControlPoint*); + virtual void line_drag(uint32_t i1, uint32_t i2, float, bool with_push); + + ControlPoint* nth (uint32_t); + uint32_t npoints() const { return control_points.size(); } + + string name() const { return _name; } + bool visible() const { return _visible; } + guint32 height() const { return _height; } + + void set_line_color (uint32_t); + uint32_t get_line_color() const { return _line_color; } + + void show (); + void hide (); + void set_height (guint32); + void set_verbose_cursor_uses_gain_mapping (bool yn); + + TimeAxisView& trackview; + + GtkCanvasGroup* canvas_group() const { return GTK_CANVAS_GROUP(group); } + GtkCanvasItem* parent_group() const { return _parent_group; } + GtkCanvasItem* grab_item() const { return line; } + + void show_selection(); + void hide_selection (); + + void set_point_size (double size); + + static void invalidate_point (GtkCanvasPoints*, uint32_t index); + static bool invalid_point (GtkCanvasPoints*, uint32_t index); + + virtual string get_verbose_cursor_string (float); + virtual void view_to_model_y (double&) = 0; + virtual void model_to_view_y (double&) = 0; + + ARDOUR::AutomationList& the_list() const { return alist; } + + void show_all_control_points (); + void hide_all_but_selected_control_points (); + + bool is_last_point (ControlPoint &); + bool is_first_point (ControlPoint &); + + protected: + string _name; + guint32 _height; + uint32_t _line_color; + ARDOUR::AutomationList& alist; + + bool _visible : 1; + bool _vc_uses_gain_mapping : 1; + bool terminal_points_can_slide : 1; + bool update_pending : 1; + bool no_draw : 1; + bool points_visible : 1; + + GtkCanvasItem* _parent_group; + GtkCanvasItem* group; + GtkCanvasItem* line; /* line */ + GtkCanvasPoints* point_coords; /* coordinates for canvas line */ + vector control_points; /* visible control points */ + + gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer); + + void determine_visible_control_points (GtkCanvasPoints*); + void sync_model_from (ControlPoint&); + void sync_model_with_view_point (ControlPoint&); + void sync_model_with_view_line (uint32_t, uint32_t); + void modify_view (ControlPoint&, double, double, bool with_push); + + virtual void change_model (ARDOUR::AutomationList::iterator, double x, double y); + virtual void change_model_range (ARDOUR::AutomationList::iterator,ARDOUR::AutomationList::iterator, double delta, float ydelta); + + void reset_callback (const ARDOUR::AutomationList&); + void list_changed (ARDOUR::Change); + + UndoAction get_memento(); + + + private: + uint32_t drags; + double first_drag_fraction; + double last_drag_fraction; + uint32_t line_drag_cp1; + uint32_t line_drag_cp2; + + void modify_view_point(ControlPoint&, double, double, bool with_push); + void reset_line_coords (ControlPoint&); + void update_line (); + + struct ModelRepresentation { + ARDOUR::AutomationList::iterator start; + ARDOUR::AutomationList::iterator end; + jack_nframes_t xpos; + double ypos; + jack_nframes_t xmin; + double ymin; + jack_nframes_t xmax; + double ymax; + jack_nframes_t xval; + double yval; + }; + + void model_representation (ControlPoint&, ModelRepresentation&); + + friend class AudioRegionGainLine; +}; + +#endif /* __ardour_automation_line_h__ */ + diff --git a/gtk2_ardour/automation_pan_line.cc b/gtk2_ardour/automation_pan_line.cc new file mode 100644 index 0000000000..fab4f0ba96 --- /dev/null +++ b/gtk2_ardour/automation_pan_line.cc @@ -0,0 +1,57 @@ +/* + Copyright (C) 2000-2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include + +#include "public_editor.h" +#include "automation_pan_line.h" +#include "utils.h" +#include + +#include + +using namespace ARDOUR; + +AutomationPanLine::AutomationPanLine (string name, Session& s, TimeAxisView& tv, GtkCanvasItem* parent, + Curve& c, + gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer), + gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer)) + : AutomationLine (name, tv, parent, c, point_callback, line_callback), + session (s) +{ +} + +void +AutomationPanLine::view_to_model_y (double& y) +{ + // vertical coordinate axis reversal + y = 1.0 - y; +} + +void +AutomationPanLine::model_to_view_y (double& y) +{ + // vertical coordinate axis reversal + y = 1.0 - y; +} + + diff --git a/gtk2_ardour/automation_pan_line.h b/gtk2_ardour/automation_pan_line.h new file mode 100644 index 0000000000..2fc8efbd9f --- /dev/null +++ b/gtk2_ardour/automation_pan_line.h @@ -0,0 +1,35 @@ +#ifndef __ardour_gtk_automation_pan_line_h__ +#define __ardour_gtk_automation_pan_line_h__ + +#include +#include +#include + +#include "automation_line.h" + +namespace ARDOUR { + class Session; +} + +class TimeAxisView; + +class AutomationPanLine : public AutomationLine +{ + public: + AutomationPanLine (string name, ARDOUR::Session&, TimeAxisView&, GtkCanvasItem* parent, + ARDOUR::Curve&, + gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer), + gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer)); + + void view_to_model_y (double&); + void model_to_view_y (double&); + + private: + ARDOUR::Session& session; + vector lines; +}; + + +#endif /* __ardour_gtk_automation_pan_line_h__ */ + + diff --git a/gtk2_ardour/automation_selectable.h b/gtk2_ardour/automation_selectable.h new file mode 100644 index 0000000000..9b8f78e057 --- /dev/null +++ b/gtk2_ardour/automation_selectable.h @@ -0,0 +1,21 @@ +#ifndef __ardour_gtk_automation_selectable_h__ +#define __ardour_gtk_automation_selectable_h__ + +#include +#include "selectable.h" + +class TimeAxisView; + +struct AutomationSelectable : public Selectable +{ + jack_nframes_t start; + jack_nframes_t end; + double low_fract; + double high_fract; + TimeAxisView& track; + + AutomationSelectable (jack_nframes_t s, jack_nframes_t e, double l, double h, TimeAxisView& atv) + : start (s), end (e), low_fract (l), high_fract (h), track (atv) {} +}; + +#endif /* __ardour_gtk_automation_selectable_h__ */ diff --git a/gtk2_ardour/automation_selection.h b/gtk2_ardour/automation_selection.h new file mode 100644 index 0000000000..1fec8b1d86 --- /dev/null +++ b/gtk2_ardour/automation_selection.h @@ -0,0 +1,12 @@ +#ifndef __ardour_gtk_automation_selection_h__ +#define __ardour_gtk_automation_selection_h__ + +#include + +namespace ARDOUR { + class AutomationList; +} + +struct AutomationSelection : list {}; + +#endif /* __ardour_gtk_automation_selection_h__ */ diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc new file mode 100644 index 0000000000..e90f7e61f9 --- /dev/null +++ b/gtk2_ardour/automation_time_axis.cc @@ -0,0 +1,796 @@ +#include + +#include "ardour_ui.h" +#include "automation_time_axis.h" +#include "automation_line.h" +#include "public_editor.h" +#include "canvas-simplerect.h" +#include "canvas-waveview.h" +#include "selection.h" +#include "ghostregion.h" +#include "rgb_macros.h" +#include "automation_selectable.h" +#include "point_selection.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; +using namespace Editing; + +static const gchar * small_x_xpm[] = { +"11 11 2 1", +" c None", +". c #000000", +" ", +" ", +" . . ", +" . . ", +" . . ", +" . ", +" . . ", +" . . ", +" . . ", +" ", +" "}; + +AutomationTimeAxisView::AutomationTimeAxisView (Session& s, Route& r, PublicEditor& e, TimeAxisView& rent, Widget* p, std::string nom, std::string state_name, std::string nomparent) + + : AxisView (s), + TimeAxisView (s, e, &rent, p), + route (r), + _name (nom), + _state_name (state_name), + height_button (_("h")), + clear_button (_("clear")), + auto_button (X_("")) /* force addition of a label */ +{ + automation_menu = 0; + in_destructor = false; + auto_off_item = 0; + auto_touch_item = 0; + auto_write_item = 0; + auto_play_item = 0; + ignore_state_request = false; + + base_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_display), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 1000000.0, + "outline_color_rgba", color_map[cAutomationTrackOutline], + /* outline ends and bottom */ + "outline_what", (guint32) (0x1|0x2|0x8), + "fill_color_rgba", color_map[cAutomationTrackFill], + NULL); + + gtk_object_set_data (GTK_OBJECT(base_rect), "trackview", this); + + gtk_signal_connect (GTK_OBJECT(base_rect), "event", + (GtkSignalFunc) PublicEditor::canvas_automation_track_event, + this); + + hide_button.add (*(manage (new Pixmap (small_x_xpm)))); + + height_button.set_name ("TrackSizeButton"); + auto_button.set_name ("TrackVisualButton"); + clear_button.set_name ("TrackVisualButton"); + hide_button.set_name ("TrackRemoveButton"); + + ARDOUR_UI::instance()->tooltips().set_tip(height_button, _("track height")); + ARDOUR_UI::instance()->tooltips().set_tip(auto_button, _("automation state")); + ARDOUR_UI::instance()->tooltips().set_tip(clear_button, _("clear track")); + ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("hide track")); + + /* rearrange the name display */ + + /* we never show these for automation tracks, so make + life easier and remove them. + */ + + name_hbox.remove (name_entry); + + /* move the name label over a bit */ + + string shortpname = _name; + bool shortened = false; + + if (_name.length()) { + if (shortpname.length() > 18) { + shortpname = shortpname.substr (0, 16); + shortpname += "..."; + shortened = true; + } + } + name_label.set_text (shortpname); + name_label.set_alignment (1.0, 0.5); + + if (nomparent.length()) { + + /* limit the plug name string */ + + string pname = nomparent; + + if (pname.length() > 14) { + pname = pname.substr (0, 11); + pname += "..."; + shortened = true; + } + + plugname = new Label (pname); + plugname->set_name (X_("TrackPlugName")); + plugname->set_alignment (1.0, 0.5); + name_label.set_name (X_("TrackParameterName")); + controls_table.remove (name_hbox); + controls_table.attach (*plugname, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + plugname_packed = true; + controls_table.attach (name_hbox, 1, 6, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + } else { + plugname = 0; + plugname_packed = false; + } + + if (shortened) { + string tipname = nomparent; + if (!tipname.empty()) { + tipname += ": "; + } + tipname += _name; + ARDOUR_UI::instance()->tooltips().set_tip(controls_ebox, tipname); + } + + /* add the buttons */ + controls_table.attach (hide_button, 0, 1, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + controls_table.attach (height_button, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + + controls_table.attach (auto_button, 7, 9, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + controls_table.attach (clear_button, 7, 9, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + + controls_table.show_all (); + + height_button.clicked.connect (slot (*this, &AutomationTimeAxisView::height_clicked)); + clear_button.clicked.connect (slot (*this, &AutomationTimeAxisView::clear_clicked)); + hide_button.clicked.connect (slot (*this, &AutomationTimeAxisView::hide_clicked)); + auto_button.clicked.connect (slot (*this, &AutomationTimeAxisView::auto_clicked)); + + controls_base_selected_name = X_("AutomationTrackControlsBaseSelected"); + controls_base_unselected_name = X_("AutomationTrackControlsBase"); + controls_ebox.set_name (controls_base_unselected_name); + + controls_frame.set_shadow_type (GTK_SHADOW_ETCHED_OUT); + + XMLNode* xml_node = get_parent_with_state()->get_child_xml_node (_state_name); + set_state (*xml_node); + + /* make sure labels etc. are correct */ + + automation_state_changed (); +} + +AutomationTimeAxisView::~AutomationTimeAxisView () +{ + in_destructor = true; + + for (list::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + delete *i; + } +} + +void +AutomationTimeAxisView::auto_clicked () +{ + using namespace Menu_Helpers; + + if (automation_menu == 0) { + automation_menu = manage (new Menu); + automation_menu->set_name ("ArdourContextMenu"); + MenuList& items (automation_menu->items()); + + items.push_back (MenuElem (_("off"), + bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off))); + items.push_back (MenuElem (_("play"), + bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play))); + items.push_back (MenuElem (_("write"), + bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write))); + items.push_back (MenuElem (_("touch"), + bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch))); + } + + automation_menu->popup (1, 0); +} + + +void +AutomationTimeAxisView::automation_state_changed () +{ + AutoState state; + + /* update button label */ + + if (lines.empty()) { + state = Off; + } else { + state = lines.front()->the_list().automation_state (); + } + + switch (state & (Off|Play|Touch|Write)) { + case Off: + static_cast(auto_button.get_child())->set_text (_("off")); + if (auto_off_item) { + ignore_state_request = true; + auto_off_item->set_active (true); + auto_play_item->set_active (false); + auto_touch_item->set_active (false); + auto_write_item->set_active (false); + ignore_state_request = false; + } + break; + case Play: + static_cast(auto_button.get_child())->set_text (_("play")); + if (auto_play_item) { + ignore_state_request = true; + auto_play_item->set_active (true); + auto_off_item->set_active (false); + auto_touch_item->set_active (false); + auto_write_item->set_active (false); + ignore_state_request = false; + } + break; + case Write: + static_cast(auto_button.get_child())->set_text (_("write")); + if (auto_write_item) { + ignore_state_request = true; + auto_write_item->set_active (true); + auto_off_item->set_active (false); + auto_play_item->set_active (false); + auto_touch_item->set_active (false); + ignore_state_request = false; + } + break; + case Touch: + static_cast(auto_button.get_child())->set_text (_("touch")); + if (auto_touch_item) { + ignore_state_request = true; + auto_touch_item->set_active (true); + auto_off_item->set_active (false); + auto_play_item->set_active (false); + auto_write_item->set_active (false); + ignore_state_request = false; + } + break; + default: + static_cast(auto_button.get_child())->set_text (_("???")); + break; + } +} + +void +AutomationTimeAxisView::height_clicked () +{ + popup_size_menu (0); +} + +void +AutomationTimeAxisView::clear_clicked () +{ + _session.begin_reversible_command (_("clear automation")); + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + (*i)->clear (); + } + _session.commit_reversible_command (); +} + +void +AutomationTimeAxisView::set_height (TrackHeight h) +{ + bool changed = (height != (uint32_t) h); + + TimeAxisView* state_parent = get_parent_with_state (); + XMLNode* xml_node = state_parent->get_child_xml_node (_state_name); + + controls_table.show_all (); + + TimeAxisView::set_height (h); + gtk_object_set (GTK_OBJECT(base_rect), "y2", (double) h, NULL); + + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + (*i)->set_height (h); + } + + for (list::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + (*i)->set_height (); + } + + switch (height) { + case Largest: + xml_node->add_property ("track_height", "largest"); + controls_table.remove (name_hbox); + if (plugname) { + if (plugname_packed) { + controls_table.remove (*plugname); + plugname_packed = false; + } + controls_table.attach (*plugname, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + plugname_packed = true; + controls_table.attach (name_hbox, 1, 6, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + } else { + controls_table.attach (name_hbox, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + } + controls_table.show_all (); + name_label.show (); + break; + + case Large: + xml_node->add_property ("track_height", "large"); + controls_table.remove (name_hbox); + if (plugname) { + if (plugname_packed) { + controls_table.remove (*plugname); + plugname_packed = false; + } + controls_table.attach (*plugname, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + plugname_packed = true; + } else { + controls_table.attach (name_hbox, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + } + controls_table.show_all (); + name_label.show (); + break; + + case Larger: + xml_node->add_property ("track_height", "larger"); + controls_table.remove (name_hbox); + if (plugname) { + if (plugname_packed) { + controls_table.remove (*plugname); + plugname_packed = false; + } + controls_table.attach (*plugname, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + plugname_packed = true; + } else { + controls_table.attach (name_hbox, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + } + controls_table.show_all (); + name_label.show (); + break; + + case Normal: + xml_node->add_property ("track_height", "normal"); + controls_table.remove (name_hbox); + if (plugname) { + if (plugname_packed) { + controls_table.remove (*plugname); + plugname_packed = false; + } + controls_table.attach (*plugname, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + plugname_packed = true; + controls_table.attach (name_hbox, 1, 6, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + } else { + controls_table.attach (name_hbox, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + } + controls_table.show_all (); + name_label.show (); + break; + + case Smaller: + xml_node->add_property ("track_height", "smaller"); + controls_table.remove (name_hbox); + if (plugname) { + if (plugname_packed) { + controls_table.remove (*plugname); + plugname_packed = false; + } + } + controls_table.attach (name_hbox, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + controls_table.hide_all (); + name_hbox.show_all (); + controls_table.show (); + break; + + case Small: + xml_node->add_property ("track_height", "small"); + controls_table.remove (name_hbox); + if (plugname) { + if (plugname_packed) { + controls_table.remove (*plugname); + plugname_packed = false; + } + } + controls_table.attach (name_hbox, 1, 6, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + controls_table.hide_all (); + name_hbox.show_all (); + controls_table.show (); + break; + } + + if (changed) { + /* only emit the signal if the height really changed */ + route.gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */ + } +} + +void +AutomationTimeAxisView::set_samples_per_unit (double spu) +{ + TimeAxisView::set_samples_per_unit (editor.get_current_zoom()); + + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + (*i)->reset (); + } +} + +void +AutomationTimeAxisView::hide_clicked () +{ + set_marked_for_display (false); + hide (); +} + + +void +AutomationTimeAxisView::build_display_menu () +{ + using namespace Menu_Helpers; + + /* get the size menu ready */ + + build_size_menu (); + + /* prepare it */ + + TimeAxisView::build_display_menu (); + + /* now fill it with our stuff */ + + MenuList& items = display_menu->items(); + + items.push_back (MenuElem (_("Height"), *size_menu)); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Hide"), slot (*this, &AutomationTimeAxisView::hide_clicked))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Clear"), slot (*this, &AutomationTimeAxisView::clear_clicked))); + items.push_back (SeparatorElem()); + + Menu* auto_state_menu = manage (new Menu); + auto_state_menu->set_name ("ArdourContextMenu"); + MenuList& as_items = auto_state_menu->items(); + + as_items.push_back (CheckMenuElem (_("off"), + bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Off))); + auto_off_item = dynamic_cast(as_items.back()); + + as_items.push_back (CheckMenuElem (_("play"), + bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Play))); + auto_play_item = dynamic_cast(as_items.back()); + + as_items.push_back (CheckMenuElem (_("write"), + bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Write))); + auto_write_item = dynamic_cast(as_items.back()); + + as_items.push_back (CheckMenuElem (_("touch"), + bind (slot (*this, &AutomationTimeAxisView::set_automation_state), (AutoState) Touch))); + auto_touch_item = dynamic_cast(as_items.back()); + + items.push_back (MenuElem (_("State"), *auto_state_menu)); + + /* make sure the automation menu state is correct */ + + automation_state_changed (); +} + +bool +AutomationTimeAxisView::cut_copy_clear (Selection& selection, CutCopyOp op) +{ + bool ret = false; + + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + ret = cut_copy_clear_one ((**i), selection, op); + } + + return ret; +} + +bool +AutomationTimeAxisView::cut_copy_clear_one (AutomationLine& line, Selection& selection, CutCopyOp op) +{ + AutomationList* what_we_got = 0; + AutomationList& alist (line.the_list()); + bool ret = false; + + _session.add_undo (alist.get_memento()); + + switch (op) { + case Cut: + if ((what_we_got = alist.cut (selection.time.front().start, selection.time.front().end)) != 0) { + editor.get_cut_buffer().add (what_we_got); + _session.add_redo_no_execute (alist.get_memento()); + ret = true; + } + break; + case Copy: + if ((what_we_got = alist.copy (selection.time.front().start, selection.time.front().end)) != 0) { + editor.get_cut_buffer().add (what_we_got); + } + break; + + case Clear: + if ((what_we_got = alist.cut (selection.time.front().start, selection.time.front().end)) != 0) { + _session.add_redo_no_execute (alist.get_memento()); + delete what_we_got; + what_we_got = 0; + ret = true; + } + break; + } + + if (what_we_got) { + for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) { + double foo = (*x)->value; + line.model_to_view_y (foo); + (*x)->value = foo; + } + } + + return ret; +} + +bool +AutomationTimeAxisView::cut_copy_clear_objects (PointSelection& selection, CutCopyOp op) +{ + bool ret = false; + + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + ret = cut_copy_clear_objects_one ((**i), selection, op); + } + + return ret; +} + +bool +AutomationTimeAxisView::cut_copy_clear_objects_one (AutomationLine& line, PointSelection& selection, CutCopyOp op) +{ + AutomationList* what_we_got = 0; + AutomationList& alist (line.the_list()); + bool ret = false; + + _session.add_undo (alist.get_memento()); + + for (PointSelection::iterator i = selection.begin(); i != selection.end(); ++i) { + + if (&(*i).track != this) { + continue; + } + + switch (op) { + case Cut: + if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) { + editor.get_cut_buffer().add (what_we_got); + _session.add_redo_no_execute (alist.get_memento()); + ret = true; + } + break; + case Copy: + if ((what_we_got = alist.copy ((*i).start, (*i).end)) != 0) { + editor.get_cut_buffer().add (what_we_got); + } + break; + + case Clear: + if ((what_we_got = alist.cut ((*i).start, (*i).end)) != 0) { + _session.add_redo_no_execute (alist.get_memento()); + delete what_we_got; + what_we_got = 0; + ret = true; + } + break; + } + } + + if (what_we_got) { + for (AutomationList::iterator x = what_we_got->begin(); x != what_we_got->end(); ++x) { + double foo = (*x)->value; + line.model_to_view_y (foo); + (*x)->value = foo; + } + } + + return ret; +} + +bool +AutomationTimeAxisView::paste (jack_nframes_t pos, float times, Selection& selection, size_t nth) +{ + bool ret = true; + + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + ret = paste_one (**i, pos, times, selection, nth); + } + + return ret; +} + +bool +AutomationTimeAxisView::paste_one (AutomationLine& line, jack_nframes_t pos, float times, Selection& selection, size_t nth) +{ + AutomationSelection::iterator p; + AutomationList& alist (line.the_list()); + + for (p = selection.lines.begin(); p != selection.lines.end() && nth; ++p, --nth); + + if (p == selection.lines.end()) { + return false; + } + + /* Make a copy of the list because we have to scale the + values from view coordinates to model coordinates, and we're + not supposed to modify the points in the selection. + */ + + AutomationList copy (**p); + + for (AutomationList::iterator x = copy.begin(); x != copy.end(); ++x) { + double foo = (*x)->value; + line.view_to_model_y (foo); + (*x)->value = foo; + } + + _session.add_undo (alist.get_memento()); + alist.paste (copy, pos, times); + _session.add_redo_no_execute (alist.get_memento()); + + return true; +} + +void +AutomationTimeAxisView::add_ghost (GhostRegion* gr) +{ + ghosts.push_back (gr); + gr->GoingAway.connect (slot (*this, &AutomationTimeAxisView::remove_ghost)); +} + +void +AutomationTimeAxisView::remove_ghost (GhostRegion* gr) +{ + if (in_destructor) { + return; + } + + list::iterator i; + + for (i = ghosts.begin(); i != ghosts.end(); ++i) { + if ((*i) == gr) { + ghosts.erase (i); + break; + } + } +} + +void +AutomationTimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list& results) +{ + if (!lines.empty() && touched (top, bot)) { + double topfrac; + double botfrac; + + /* remember: this is X Window - coordinate space starts in upper left and moves down. + y_position is the "origin" or "top" of the track. + */ + + double mybot = y_position + height; // XXX need to include Editor::track_spacing; + + if (y_position >= top && mybot <= bot) { + + /* y_position is below top, mybot is above bot, so we're fully + covered vertically. + */ + + topfrac = 1.0; + botfrac = 0.0; + + } else { + + /* top and bot are within y_position .. mybot */ + + topfrac = 1.0 - ((top - y_position) / height); + botfrac = 1.0 - ((bot - y_position) / height); + } + + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + (*i)->get_selectables (start, end, botfrac, topfrac, results); + } + } +} + +void +AutomationTimeAxisView::get_inverted_selectables (Selection& sel, list& result) +{ + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + (*i)->get_inverted_selectables (sel, result); + } +} + +void +AutomationTimeAxisView::set_selected_points (PointSelection& points) +{ + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + (*i)->set_selected_points (points); + } +} + +void +AutomationTimeAxisView::clear_lines () +{ + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + delete *i; + } + + lines.clear (); + automation_connection.disconnect (); +} + +void +AutomationTimeAxisView::add_line (AutomationLine& line) +{ + bool get = false; + + if (lines.empty()) { + /* first line is the Model for automation state */ + automation_connection = line.the_list().automation_state_changed.connect + (slot (*this, &AutomationTimeAxisView::automation_state_changed)); + get = true; + } + + lines.push_back (&line); + line.set_height (height); + + if (get) { + /* pick up the current state */ + automation_state_changed (); + } +} + +void +AutomationTimeAxisView::show_all_control_points () +{ + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + (*i)->show_all_control_points (); + } +} + +void +AutomationTimeAxisView::hide_all_but_selected_control_points () +{ + for (vector::iterator i = lines.begin(); i != lines.end(); ++i) { + (*i)->hide_all_but_selected_control_points (); + } +} + +void +AutomationTimeAxisView::entered() +{ + show_all_control_points (); +} + +void +AutomationTimeAxisView::exited () +{ + hide_all_but_selected_control_points (); +} + +void +AutomationTimeAxisView::set_state (const XMLNode& node) +{ + TimeAxisView::set_state (node); +} + +XMLNode* +AutomationTimeAxisView::get_state_node () +{ + TimeAxisView* state_parent = get_parent_with_state (); + + if (state_parent) { + return state_parent->get_child_xml_node (_state_name); + } else { + return 0; + } +} diff --git a/gtk2_ardour/automation_time_axis.h b/gtk2_ardour/automation_time_axis.h new file mode 100644 index 0000000000..55f402aa1c --- /dev/null +++ b/gtk2_ardour/automation_time_axis.h @@ -0,0 +1,121 @@ +#ifndef __ardour_gtk_automation_time_axis_h__ +#define __ardour_gtk_automation_time_axis_h__ + +#include +#include +#include +#include + +#include "time_axis_view.h" + +using std::vector; +using std::list; +using std::string; + +namespace ARDOUR { + class Session; + class Route; +} + +namespace Gtk { + class Widget; +} + +class PublicEditor; +class TimeSelection; +class AudioRegionSelection; +class PointSelection; +class AutomationLine; +class GhostRegion; +class Selection; +class Selectable; + +class AutomationTimeAxisView : public TimeAxisView { + public: + AutomationTimeAxisView (ARDOUR::Session&, + ARDOUR::Route&, + PublicEditor&, + TimeAxisView& parent, + Gtk::Widget* parent, + std::string name, /* translatable */ + std::string state_name, /* not translatable */ + std::string plug_name = ""); + + ~AutomationTimeAxisView(); + + void set_height (TimeAxisView::TrackHeight); + void set_samples_per_unit (double); + std::string name() const { return _name; } + + virtual void add_automation_event (GtkCanvasItem *item, GdkEvent *event, jack_nframes_t, double) = 0; + + void clear_lines (); + void add_line (AutomationLine&); + + vector lines; + + void set_selected_points (PointSelection&); + void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list&); + void get_inverted_selectables (Selection&, list& results); + + void show_timestretch (jack_nframes_t start, jack_nframes_t end) {} + void hide_timestretch () {} + + /* editing operations */ + + bool cut_copy_clear (Selection&, Editing::CutCopyOp); + bool cut_copy_clear_objects (PointSelection&, Editing::CutCopyOp); + bool paste (jack_nframes_t, float times, Selection&, size_t nth); + + void add_ghost (GhostRegion*); + void remove_ghost (GhostRegion*); + + void show_all_control_points (); + void hide_all_but_selected_control_points (); + void set_state (const XMLNode&); + XMLNode* get_state_node (); + + protected: + ARDOUR::Route& route; + GtkCanvasItem* base_rect; + string _name; + string _state_name; + bool in_destructor; + + Gtk::Button hide_button; + Gtk::Button height_button; + Gtk::Button clear_button; + Gtk::Button auto_button; + Gtk::Menu* automation_menu; + Gtk::Label* plugname; + bool plugname_packed; + + Gtk::CheckMenuItem* auto_off_item; + Gtk::CheckMenuItem* auto_play_item; + Gtk::CheckMenuItem* auto_touch_item; + Gtk::CheckMenuItem* auto_write_item; + + void clear_clicked (); + void height_clicked (); + void hide_clicked (); + void auto_clicked (); + + virtual void build_display_menu (); + + list ghosts; + + bool cut_copy_clear_one (AutomationLine&, Selection&, Editing::CutCopyOp); + bool cut_copy_clear_objects_one (AutomationLine&, PointSelection&, Editing::CutCopyOp); + bool paste_one (AutomationLine&, jack_nframes_t, float times, Selection&, size_t nth); + + virtual void set_automation_state (ARDOUR::AutoState) = 0; + bool ignore_state_request; + + void automation_state_changed (); + SigC::Connection automation_connection; + + void entered (); + void exited (); +}; + +#endif /* __ardour_gtk_automation_time_axis_h__ */ diff --git a/gtk2_ardour/axis_view.cc b/gtk2_ardour/axis_view.cc new file mode 100644 index 0000000000..419877e75a --- /dev/null +++ b/gtk2_ardour/axis_view.cc @@ -0,0 +1,96 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include + +#include +#include + +#include "public_editor.h" +#include "axis_view.h" +#include "i18n.h" + +using namespace Gtk; +using namespace Gtkmmext; + + +list AxisView::used_colors; + +AxisView::AxisView (ARDOUR::Session& sess) : _session(sess) +{ + _selected = false; +} + +AxisView::~AxisView() +{ + +} + +GdkColor +AxisView::unique_random_color() +{ + GdkColor newcolor; + + while (1) { + + /* avoid neon/glowing tones by limiting them to the + "inner section" (paler) of a color wheel/circle. + */ + + const int32_t max_saturation = 48000; // 65535 would open up the whole color wheel + + newcolor.red = random() % max_saturation; + newcolor.blue = random() % max_saturation; + newcolor.green = random() % max_saturation; + + if (used_colors.size() == 0) { + used_colors.push_back (newcolor); + return newcolor; + } + + for (list::iterator i = used_colors.begin(); i != used_colors.end(); ++i) { + GdkColor c = *i; + float rdelta, bdelta, gdelta; + + rdelta = newcolor.red - c.red; + bdelta = newcolor.blue - c.blue; + gdelta = newcolor.green - c.green; + + if (sqrt (rdelta*rdelta + bdelta*bdelta + gdelta*gdelta) > 25.0) { + used_colors.push_back (newcolor); + return newcolor; + } + } + + /* XXX need throttle here to make sure we don't spin for ever */ + } +} diff --git a/gtk2_ardour/axis_view.h b/gtk2_ardour/axis_view.h new file mode 100644 index 0000000000..5fc6917b74 --- /dev/null +++ b/gtk2_ardour/axis_view.h @@ -0,0 +1,97 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_axis_view_h__ +#define __ardour_gtk_axis_view_h__ + +#include +#include +#include +#include "prompter.h" + +namespace ARDOUR { + class Session; +} + +/** + * AxisView defines the abstract base class for time-axis trackviews and routes. + * + */ +class AxisView : public SigC::Object +{ + public: + /** + * Returns the current 'Track' Color + * + * @return the current Track Color + */ + Gdk_Color color() const { return _color; } + + ARDOUR::Session& session() const { return _session; } + + virtual string name() const = 0; + + virtual void set_selected (bool yn) { + if (yn != _selected) { + _selected = yn; + } + } + + virtual bool marked_for_display() const { return _marked_for_display; } + + virtual void set_marked_for_display (bool yn) { + if (yn != _marked_for_display) { + _marked_for_display = yn; + } + } + + virtual bool selected() const { return _selected; } + SigC::Signal0 Hiding; + SigC::Signal0 GoingAway; + + protected: + + AxisView (ARDOUR::Session& sess); + virtual ~AxisView(); + + + /** + * Generate a new random TrackView color, unique from those colors already used. + * + * @return the unique random color. + */ + static GdkColor unique_random_color(); + + + ARDOUR::Session& _session; + Gdk_Color _color; + + static list used_colors; + + Gtk::Label name_label; + + bool _selected; + + bool _marked_for_display; + +}; /* class AxisView */ + +#endif /* __ardour_gtk_axis_view_h__ */ + diff --git a/gtk2_ardour/canvas-curve.h b/gtk2_ardour/canvas-curve.h new file mode 100644 index 0000000000..4727c3d1d3 --- /dev/null +++ b/gtk2_ardour/canvas-curve.h @@ -0,0 +1,66 @@ +/* gtk-canvas-curve.h: GtkCanvas item for constrained spline curves + * + * Copyright (C) 2003 Paul Davis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef __GTK_CANVAS_CURVE_H__ +#define __GTK_CANVAS_CURVE_H__ + +#include +#include "gtk-canvas/gtk-canvas.h" + +BEGIN_GTK_CANVAS_DECLS + +/* Wave viewer item for canvas. + */ + +#define GTK_CANVAS_TYPE_CANVAS_CURVE (gtk_canvas_curve_get_type ()) +#define GTK_CANVAS_CURVE(obj) (GTK_CHECK_CAST ((obj), GTK_CANVAS_TYPE_CANVAS_CURVE, GtkCanvasCurve)) +#define GTK_CANVAS_CURVE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_CANVAS_TYPE_CANVAS_CURVE, GtkCanvasCurveClass)) +#define GTK_CANVAS_IS_CANVAS_CURVE(obj) (GTK_CHECK_TYPE ((obj), GTK_CANVAS_TYPE_CANVAS_CURVE)) +#define GTK_CANVAS_IS_CANVAS_CURVE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_CANVAS_TYPE_CANVAS_CURVE)) + +typedef struct _GtkCanvasCurve GtkCanvasCurve; +typedef struct _GtkCanvasCurveClass GtkCanvasCurveClass; + +struct _GtkCanvasCurve +{ + GtkCanvasItem item; + double x1, y1, x2, y2; + void* curve_arg; + float* vector; + size_t veclen; + uint32_t color; + + /* cached values set during update/used during render */ + + unsigned char r, b, g, a; + guint32 bbox_ulx, bbox_uly; + guint32 bbox_lrx, bbox_lry; +}; + +struct _GtkCanvasCurveClass { + GtkCanvasItemClass parent_class; +}; + +GtkType gtk_canvas_curve_get_type (void); + +END_GTK_CANVAS_DECLS + +#endif /* __GTK_CANVAS_CURVE_H__ */ diff --git a/gtk2_ardour/canvas-imageframe.c b/gtk2_ardour/canvas-imageframe.c new file mode 100644 index 0000000000..d186e86f50 --- /dev/null +++ b/gtk2_ardour/canvas-imageframe.c @@ -0,0 +1,586 @@ +/* Image item type for GtkCanvas widget + * + * GtkCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is + * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties. + * + * Copyright (C) 1998 The Free Software Foundation + * + * Author: Federico Mena + */ + + +#include /* for memcpy() */ +#include +#include +#include "libart_lgpl/art_misc.h" +#include "libart_lgpl/art_affine.h" +#include "libart_lgpl/art_pixbuf.h" +#include "libart_lgpl/art_rgb_pixbuf_affine.h" +#include "canvas-imageframe.h" +#include +#include + + +enum { + ARG_0, + ARG_PIXBUF, + ARG_X, + ARG_Y, + ARG_WIDTH, + ARG_HEIGHT, + ARG_DRAWWIDTH, + ARG_ANCHOR +}; + + +static void gtk_canvas_imageframe_class_init(GtkCanvasImageFrameClass* class) ; +static void gtk_canvas_imageframe_init(GtkCanvasImageFrame* image) ; +static void gtk_canvas_imageframe_destroy(GtkObject* object) ; +static void gtk_canvas_imageframe_set_arg(GtkObject* object, GtkArg* arg, guint arg_id) ; +static void gtk_canvas_imageframe_get_arg(GtkObject* object, GtkArg* arg, guint arg_id) ; + +static void gtk_canvas_imageframe_update(GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) ; +static void gtk_canvas_imageframe_realize(GtkCanvasItem *item) ; +static void gtk_canvas_imageframe_unrealize(GtkCanvasItem *item) ; +static void gtk_canvas_imageframe_draw(GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) ; +static double gtk_canvas_imageframe_point(GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item) ; +static void gtk_canvas_imageframe_translate(GtkCanvasItem *item, double dx, double dy) ; +static void gtk_canvas_imageframe_bounds(GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2) ; +static void gtk_canvas_imageframe_render(GtkCanvasItem *item, GtkCanvasBuf *buf) ; + +static GtkCanvasItemClass *parent_class; + + +GtkType +gtk_canvas_imageframe_get_type (void) +{ + static GtkType imageframe_type = 0; + + if (!imageframe_type) { + GtkTypeInfo imageframe_info = { + "GtkCanvasImageFrame", + sizeof (GtkCanvasImageFrame), + sizeof (GtkCanvasImageFrameClass), + (GtkClassInitFunc) gtk_canvas_imageframe_class_init, + (GtkObjectInitFunc) gtk_canvas_imageframe_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + imageframe_type = gtk_type_unique (gtk_canvas_item_get_type (), &imageframe_info); + } + + return imageframe_type; +} + +static void +gtk_canvas_imageframe_class_init (GtkCanvasImageFrameClass *class) +{ + GtkObjectClass *object_class; + GtkCanvasItemClass *item_class; + + object_class = (GtkObjectClass *) class; + item_class = (GtkCanvasItemClass *) class; + + parent_class = gtk_type_class (gtk_canvas_item_get_type ()); + + gtk_object_add_arg_type ("GtkCanvasImageFrame::pixbuf", GTK_TYPE_BOXED, GTK_ARG_WRITABLE, ARG_PIXBUF); + gtk_object_add_arg_type ("GtkCanvasImageFrame::x", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X); + gtk_object_add_arg_type ("GtkCanvasImageFrame::y", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y); + gtk_object_add_arg_type ("GtkCanvasImageFrame::width", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_WIDTH); + gtk_object_add_arg_type ("GtkCanvasImageFrame::drawwidth", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_DRAWWIDTH); + gtk_object_add_arg_type ("GtkCanvasImageFrame::height", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_HEIGHT); + gtk_object_add_arg_type ("GtkCanvasImageFrame::anchor", GTK_TYPE_ANCHOR_TYPE, GTK_ARG_READWRITE, ARG_ANCHOR); + + object_class->destroy = gtk_canvas_imageframe_destroy; + object_class->set_arg = gtk_canvas_imageframe_set_arg; + object_class->get_arg = gtk_canvas_imageframe_get_arg; + + item_class->update = gtk_canvas_imageframe_update; + item_class->realize = gtk_canvas_imageframe_realize; + item_class->unrealize = gtk_canvas_imageframe_unrealize; + item_class->draw = gtk_canvas_imageframe_draw; + item_class->point = gtk_canvas_imageframe_point; + item_class->translate = gtk_canvas_imageframe_translate; + item_class->bounds = gtk_canvas_imageframe_bounds; + item_class->render = gtk_canvas_imageframe_render; +} + +static void +gtk_canvas_imageframe_init (GtkCanvasImageFrame *image) +{ + image->x = 0.0; + image->y = 0.0; + image->width = 0.0; + image->height = 0.0; + image->drawwidth = 0.0; + image->anchor = GTK_ANCHOR_CENTER; + GTK_CANVAS_ITEM(image)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW; +} + +static void +gtk_canvas_imageframe_destroy (GtkObject *object) +{ + GtkCanvasImageFrame *image; + + g_return_if_fail (object != NULL); + g_return_if_fail (GTK_CANVAS_IS_CANVAS_IMAGEFRAME (object)); + + image = GTK_CANVAS_IMAGEFRAME (object); + + image->cwidth = 0; + image->cheight = 0; + + if (image->pixbuf) + { + art_pixbuf_free (image->pixbuf); + image->pixbuf = NULL; + } + + if(GTK_OBJECT_CLASS (parent_class)->destroy) + { + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); + } +} + +/* Get's the image bounds expressed as item-relative coordinates. */ +static void +get_bounds_item_relative (GtkCanvasImageFrame *image, double *px1, double *py1, double *px2, double *py2) +{ + GtkCanvasItem *item; + double x, y; + + item = GTK_CANVAS_ITEM (image); + + /* Get item coordinates */ + + x = image->x; + y = image->y; + + /* Anchor image */ + + switch (image->anchor) { + case GTK_ANCHOR_NW: + case GTK_ANCHOR_W: + case GTK_ANCHOR_SW: + break; + + case GTK_ANCHOR_N: + case GTK_ANCHOR_CENTER: + case GTK_ANCHOR_S: + x -= image->width / 2; + break; + + case GTK_ANCHOR_NE: + case GTK_ANCHOR_E: + case GTK_ANCHOR_SE: + x -= image->width; + break; + } + + switch (image->anchor) { + case GTK_ANCHOR_NW: + case GTK_ANCHOR_N: + case GTK_ANCHOR_NE: + break; + + case GTK_ANCHOR_W: + case GTK_ANCHOR_CENTER: + case GTK_ANCHOR_E: + y -= image->height / 2; + break; + + case GTK_ANCHOR_SW: + case GTK_ANCHOR_S: + case GTK_ANCHOR_SE: + y -= image->height; + break; + } + + /* Bounds */ + + *px1 = x; + *py1 = y; + *px2 = x + image->width; + *py2 = y + image->height; +} + +static void +get_bounds (GtkCanvasImageFrame *image, double *px1, double *py1, double *px2, double *py2) +{ + GtkCanvasItem *item; + double i2c[6]; + ArtDRect i_bbox, c_bbox; + + item = GTK_CANVAS_ITEM (image); + + gtk_canvas_item_i2c_affine (item, i2c); + + get_bounds_item_relative (image, &i_bbox.x0, &i_bbox.y0, &i_bbox.x1, &i_bbox.y1); + art_drect_affine_transform (&c_bbox, &i_bbox, i2c); + + /* add a fudge factor */ + *px1 = c_bbox.x0 - 1; + *py1 = c_bbox.y0 - 1; + *px2 = c_bbox.x1 + 1; + *py2 = c_bbox.y1 + 1; +} + +/* deprecated */ +static void +recalc_bounds (GtkCanvasImageFrame *image) +{ + GtkCanvasItem *item; + + item = GTK_CANVAS_ITEM (image); + + get_bounds (image, &item->x1, &item->y1, &item->x2, &item->y2); + + item->x1 = image->cx; + item->y1 = image->cy; + item->x2 = image->cx + image->cwidth; + item->y2 = image->cy + image->cheight; + + gtk_canvas_group_child_bounds (GTK_CANVAS_GROUP (item->parent), item); +} + +static void +gtk_canvas_imageframe_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GtkCanvasItem *item; + GtkCanvasImageFrame *image; + int update; + int calc_bounds; + + item = GTK_CANVAS_ITEM (object); + image = GTK_CANVAS_IMAGEFRAME (object); + + update = FALSE; + calc_bounds = FALSE; + + switch (arg_id) { + case ARG_PIXBUF: + if (item->canvas->aa && GTK_VALUE_BOXED (*arg)) { + if (image->pixbuf != NULL) + art_pixbuf_free (image->pixbuf); + image->pixbuf = GTK_VALUE_BOXED (*arg); + } + update = TRUE; + break; + + case ARG_X: + image->x = GTK_VALUE_DOUBLE (*arg); + update = TRUE; + break; + + case ARG_Y: + image->y = GTK_VALUE_DOUBLE (*arg); + update = TRUE; + break; + + case ARG_WIDTH: + image->width = fabs (GTK_VALUE_DOUBLE (*arg)); + update = TRUE; + break; + + case ARG_HEIGHT: + image->height = fabs (GTK_VALUE_DOUBLE (*arg)); + update = TRUE; + break; + + case ARG_DRAWWIDTH: + image->drawwidth = fabs (GTK_VALUE_DOUBLE (*arg)); + update = TRUE; + break; + + case ARG_ANCHOR: + image->anchor = GTK_VALUE_ENUM (*arg); + update = TRUE; + break; + + default: + break; + } + +#ifdef OLD_XFORM + if (update) + (* GTK_CANVAS_ITEM_CLASS (item->object.klass)->update) (item, NULL, NULL, 0); + + if (calc_bounds) + recalc_bounds (image); +#else + if (update) + gtk_canvas_item_request_update (item); +#endif +} + +static void +gtk_canvas_imageframe_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GtkCanvasImageFrame *image; + + image = GTK_CANVAS_IMAGEFRAME (object); + + switch (arg_id) { + + case ARG_X: + GTK_VALUE_DOUBLE (*arg) = image->x; + break; + + case ARG_Y: + GTK_VALUE_DOUBLE (*arg) = image->y; + break; + + case ARG_WIDTH: + GTK_VALUE_DOUBLE (*arg) = image->width; + break; + + case ARG_HEIGHT: + GTK_VALUE_DOUBLE (*arg) = image->height; + break; + + case ARG_DRAWWIDTH: + GTK_VALUE_DOUBLE (*arg) = image->drawwidth; + break; + + case ARG_ANCHOR: + GTK_VALUE_ENUM (*arg) = image->anchor; + break; + + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +gtk_canvas_imageframe_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + GtkCanvasImageFrame *image; + ArtDRect i_bbox, c_bbox; + int w = 0; + int h = 0; + + image = GTK_CANVAS_IMAGEFRAME (item); + + if (parent_class->update) + (* parent_class->update) (item, affine, clip_path, flags); + + /* only works for non-rotated, non-skewed transforms */ + image->cwidth = (int) (image->width * affine[0] + 0.5); + image->cheight = (int) (image->height * affine[3] + 0.5); + + if (image->pixbuf) { + image->need_recalc = TRUE ; + } + +#ifdef OLD_XFORM + recalc_bounds (image); +#else + get_bounds_item_relative (image, &i_bbox.x0, &i_bbox.y0, &i_bbox.x1, &i_bbox.y1); + art_drect_affine_transform (&c_bbox, &i_bbox, affine); + + /* these values only make sense in the non-rotated, non-skewed case */ + image->cx = c_bbox.x0; + image->cy = c_bbox.y0; + + /* add a fudge factor */ + c_bbox.x0--; + c_bbox.y0--; + c_bbox.x1++; + c_bbox.y1++; + + gtk_canvas_update_bbox (item, c_bbox.x0, c_bbox.y0, c_bbox.x1, c_bbox.y1); + + if (image->pixbuf) { + w = image->pixbuf->width; + h = image->pixbuf->height; + } + + image->affine[0] = (affine[0] * image->width) / w; + image->affine[1] = (affine[1] * image->height) / h; + image->affine[2] = (affine[2] * image->width) / w; + image->affine[3] = (affine[3] * image->height) / h; + image->affine[4] = i_bbox.x0 * affine[0] + i_bbox.y0 * affine[2] + affine[4]; + image->affine[5] = i_bbox.x0 * affine[1] + i_bbox.y0 * affine[3] + affine[5]; + +#endif +} + +static void +gtk_canvas_imageframe_realize (GtkCanvasItem *item) +{ + GtkCanvasImageFrame *image; + + image = GTK_CANVAS_IMAGEFRAME (item); + + if (parent_class->realize) + (* parent_class->realize) (item); + +} + +static void +gtk_canvas_imageframe_unrealize (GtkCanvasItem *item) +{ + GtkCanvasImageFrame *image; + + image = GTK_CANVAS_IMAGEFRAME(item); + + if (parent_class->unrealize) + (* parent_class->unrealize) (item); +} + +static void +recalc_if_needed (GtkCanvasImageFrame *image) +{} + +static void +gtk_canvas_imageframe_draw (GtkCanvasItem *item, GdkDrawable *drawable, + int x, int y, int width, int height) +{ + fprintf(stderr, "please don't use the CanvasImageFrame item in a non-aa Canvas\n") ; + abort() ; +} + +static double +gtk_canvas_imageframe_point (GtkCanvasItem *item, double x, double y, + int cx, int cy, GtkCanvasItem **actual_item) +{ + GtkCanvasImageFrame *image; + int x1, y1, x2, y2; + int dx, dy; + + image = GTK_CANVAS_IMAGEFRAME (item); + + *actual_item = item; + + recalc_if_needed (image); + + x1 = image->cx - item->canvas->close_enough; + y1 = image->cy - item->canvas->close_enough; + x2 = image->cx + image->cwidth - 1 + item->canvas->close_enough; + y2 = image->cy + image->cheight - 1 + item->canvas->close_enough; + + /* Hard case: is point inside image's gravity region? */ + + //if ((cx >= x1) && (cy >= y1) && (cx <= x2) && (cy <= y2)) + //return dist_to_mask (image, cx, cy) / item->canvas->pixels_per_unit; + + /* Point is outside image */ + + x1 += item->canvas->close_enough; + y1 += item->canvas->close_enough; + x2 -= item->canvas->close_enough; + y2 -= item->canvas->close_enough; + + if (cx < x1) + dx = x1 - cx; + else if (cx > x2) + dx = cx - x2; + else + dx = 0; + + if (cy < y1) + dy = y1 - cy; + else if (cy > y2) + dy = cy - y2; + else + dy = 0; + + return sqrt (dx * dx + dy * dy) / item->canvas->pixels_per_unit; +} + +static void +gtk_canvas_imageframe_translate (GtkCanvasItem *item, double dx, double dy) +{ +#ifdef OLD_XFORM + GtkCanvasImageFrame *image; + + image = GTK_CANVAS_IMAGEFRAME (item); + + image->x += dx; + image->y += dy; + + recalc_bounds (image); +#endif +} + +static void +gtk_canvas_imageframe_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2) +{ + GtkCanvasImageFrame *image; + + image = GTK_CANVAS_IMAGEFRAME (item); + + *x1 = image->x; + *y1 = image->y; + + switch (image->anchor) { + case GTK_ANCHOR_NW: + case GTK_ANCHOR_W: + case GTK_ANCHOR_SW: + break; + + case GTK_ANCHOR_N: + case GTK_ANCHOR_CENTER: + case GTK_ANCHOR_S: + *x1 -= image->width / 2.0; + break; + + case GTK_ANCHOR_NE: + case GTK_ANCHOR_E: + case GTK_ANCHOR_SE: + *x1 -= image->width; + break; + } + + switch (image->anchor) { + case GTK_ANCHOR_NW: + case GTK_ANCHOR_N: + case GTK_ANCHOR_NE: + break; + + case GTK_ANCHOR_W: + case GTK_ANCHOR_CENTER: + case GTK_ANCHOR_E: + *y1 -= image->height / 2.0; + break; + + case GTK_ANCHOR_SW: + case GTK_ANCHOR_S: + case GTK_ANCHOR_SE: + *y1 -= image->height; + break; + } + + *x2 = *x1 + image->width; + *y2 = *y1 + image->height; +} + +static void +gtk_canvas_imageframe_render (GtkCanvasItem *item, GtkCanvasBuf *buf) +{ + GtkCanvasImageFrame *image; + + image = GTK_CANVAS_IMAGEFRAME (item); + + gtk_canvas_buf_ensure_buf (buf); + +#ifdef VERBOSE + { + char str[128]; + art_affine_to_string (str, image->affine); + g_print ("gtk_canvas_imageframe_render %s\n", str); + } +#endif + + art_rgb_pixbuf_affine (buf->buf, + buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1, + buf->buf_rowstride, + image->pixbuf, + image->affine, + ART_FILTER_NEAREST, NULL); + + buf->is_bg = 0; +} diff --git a/gtk2_ardour/canvas-imageframe.h b/gtk2_ardour/canvas-imageframe.h new file mode 100644 index 0000000000..408814b8fc --- /dev/null +++ b/gtk2_ardour/canvas-imageframe.h @@ -0,0 +1,80 @@ +/* Image item type for GtkCanvas widget + * + * GtkCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is + * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties. + * + * Copyright (C) 1998 The Free Software Foundation + * + * Author: Federico Mena + */ + + +#ifndef __GTK_CANVAS_IMAGEFRAME_H__ +#define __GTK_CANVAS_IMAGEFRAME_H__ + +#include + +#include +#include /* why the hell is GtkAnchorType here and not in gtkenums.h? */ +#include +#include +#include "gtk-canvas/gtk-canvas.h" + + +BEGIN_GTK_CANVAS_DECLS + + +/* Image item for the canvas. Images are positioned by anchoring them to a point. + * The following arguments are available: + * + * name type read/write description + * ------------------------------------------------------------------------------------------ + * pixbuf ArtPixBuf* W Pointer to an ArtPixBuf (aa-mode) + * x double RW X coordinate of anchor point + * y double RW Y coordinate of anchor point + * width double RW Width to scale image to, in canvas units + * height double RW Height to scale image to, in canvas units + * drawwidth double RW Width to scale image to, in canvas units + * anchor GtkAnchorType RW Anchor side for the image + */ + + +#define GTK_CANVAS_TYPE_CANVAS_IMAGEFRAME (gtk_canvas_imageframe_get_type ()) +#define GTK_CANVAS_IMAGEFRAME(obj) (GTK_CHECK_CAST ((obj), GTK_CANVAS_TYPE_CANVAS_IMAGEFRAME, GtkCanvasImageFrame)) +#define GTK_CANVAS_IMAGEFRAME_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_CANVAS_TYPE_CANVAS_IMAGEFRAME, GtkCanvasImageFrameClass)) +#define GTK_CANVAS_IS_CANVAS_IMAGEFRAME(obj) (GTK_CHECK_TYPE ((obj), GTK_CANVAS_TYPE_CANVAS_IMAGEFRAME)) +#define GTK_CANVAS_IS_CANVAS_IMAGEFRAME_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_CANVAS_TYPE_CANVAS_IMAGEFRAME)) + + +typedef struct _GtkCanvasImageFrame GtkCanvasImageFrame; +typedef struct _GtkCanvasImageFrameClass GtkCanvasImageFrameClass; + +struct _GtkCanvasImageFrame { + GtkCanvasItem item; + + double x, y; /* Position at anchor, item relative */ + double width, height; /* Size of image, item relative */ + double drawwidth ; /* the amount of the image we draw width-wise (0-drawwidth)*/ + GtkAnchorType anchor; /* Anchor side for image */ + + int cx, cy; /* Top-left canvas coordinates for display */ + int cwidth, cheight; /* Rendered size in pixels */ + + uint32_t need_recalc : 1; /* Do we need to rescale the image? */ + + ArtPixBuf *pixbuf; /* A pixbuf, for aa rendering */ + double affine[6]; /* The item -> canvas affine */ +}; + +struct _GtkCanvasImageFrameClass { + GtkCanvasItemClass parent_class; +}; + + +/* Standard Gtk function */ +GtkType gtk_canvas_imageframe_get_type (void); + + +END_GTK_CANVAS_DECLS + +#endif diff --git a/gtk2_ardour/canvas-ruler.c b/gtk2_ardour/canvas-ruler.c new file mode 100644 index 0000000000..07b7553431 --- /dev/null +++ b/gtk2_ardour/canvas-ruler.c @@ -0,0 +1,381 @@ +#include +#include +#include + +#include "canvas-ruler.h" +#include "rgb_macros.h" + +enum { + ARG_0, + ARG_X1, + ARG_Y1, + ARG_X2, + ARG_Y2, + ARG_FRAMES_PER_UNIT, + ARG_FILL_COLOR, + ARG_TICK_COLOR + +}; + +static void gtk_canvas_ruler_class_init (GtkCanvasRulerClass *class); +static void gtk_canvas_ruler_init (GtkCanvasRuler *ruler); +static void gtk_canvas_ruler_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void gtk_canvas_ruler_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); + +static void gtk_canvas_ruler_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags); +static void gtk_canvas_ruler_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2); +static double gtk_canvas_ruler_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item); +static void gtk_canvas_ruler_render (GtkCanvasItem *item, GtkCanvasBuf *buf); +static void gtk_canvas_ruler_draw (GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h); + +static GtkCanvasItemClass *parent_class; + + +GtkType +gtk_canvas_ruler_get_type (void) +{ + static GtkType ruler_type = 0; + + if (!ruler_type) { + GtkTypeInfo ruler_info = { + "GtkCanvasRuler", + sizeof (GtkCanvasRuler), + sizeof (GtkCanvasRulerClass), + (GtkClassInitFunc) gtk_canvas_ruler_class_init, + (GtkObjectInitFunc) gtk_canvas_ruler_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + ruler_type = gtk_type_unique (gtk_canvas_item_get_type (), &ruler_info); + } + + return ruler_type; +} + +static void +gtk_canvas_ruler_class_init (GtkCanvasRulerClass *class) +{ + GtkObjectClass *object_class; + GtkCanvasItemClass *item_class; + + object_class = (GtkObjectClass *) class; + item_class = (GtkCanvasItemClass *) class; + + parent_class = gtk_type_class (gtk_canvas_item_get_type ()); + + gtk_object_add_arg_type ("GtkCanvasRuler::x1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X1); + gtk_object_add_arg_type ("GtkCanvasRuler::y1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y1); + gtk_object_add_arg_type ("GtkCanvasRuler::x2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X2); + gtk_object_add_arg_type ("GtkCanvasRuler::y2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y2); + gtk_object_add_arg_type ("GtkCanvasRuler::frames_per_unit", GTK_TYPE_LONG, GTK_ARG_READWRITE, ARG_FRAMES_PER_UNIT); + gtk_object_add_arg_type ("GtkCanvasRuler::fill_color", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_FILL_COLOR); + gtk_object_add_arg_type ("GtkCanvasRuler::tick_color", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_TICK_COLOR); + + object_class->set_arg = gtk_canvas_ruler_set_arg; + object_class->get_arg = gtk_canvas_ruler_get_arg; + + item_class->update = gtk_canvas_ruler_update; + item_class->bounds = gtk_canvas_ruler_bounds; + item_class->point = gtk_canvas_ruler_point; + item_class->render = gtk_canvas_ruler_render; + item_class->draw = gtk_canvas_ruler_draw; +} + +static void +gtk_canvas_ruler_init (GtkCanvasRuler *ruler) +{ + ruler->x1 = 0.0; + ruler->y1 = 0.0; + ruler->x2 = 0.0; + ruler->y2 = 0.0; + ruler->frames_per_unit = 1; + ruler->fill_color = 0; + ruler->tick_color = 0; + + GTK_CANVAS_ITEM(ruler)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW; +} + +static void +gtk_canvas_ruler_reset_bounds (GtkCanvasItem *item) + +{ + double x1, x2, y1, y2; + ArtPoint i1, i2; + ArtPoint w1, w2; + int Ix1, Ix2, Iy1, Iy2; + double i2w[6]; + + gtk_canvas_ruler_bounds (item, &x1, &y1, &x2, &y2); + + i1.x = x1; + i1.y = y1; + i2.x = x2; + i2.y = y2; + + gtk_canvas_item_i2w_affine (item, i2w); + art_affine_point (&w1, &i1, i2w); + art_affine_point (&w2, &i2, i2w); + + Ix1 = (int) rint(w1.x); + Ix2 = (int) rint(w2.x); + Iy1 = (int) rint(w1.y); + Iy2 = (int) rint(w2.y); + + gtk_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2); +} + +/* + * CANVAS CALLBACKS + */ + +static void +gtk_canvas_ruler_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GtkCanvasItem *item; + GtkCanvasRuler *ruler; + int redraw; + int calc_bounds; + + item = GTK_CANVAS_ITEM (object); + ruler = GTK_CANVAS_RULER (object); + + redraw = FALSE; + calc_bounds = FALSE; + + switch (arg_id) { + case ARG_X1: + if (ruler->x1 != GTK_VALUE_DOUBLE (*arg)) { + ruler->x1 = GTK_VALUE_DOUBLE (*arg); + calc_bounds = TRUE; + } + break; + + case ARG_Y1: + if (ruler->y1 != GTK_VALUE_DOUBLE (*arg)) { + ruler->y1 = GTK_VALUE_DOUBLE (*arg); + calc_bounds = TRUE; + } + break; + + case ARG_X2: + if (ruler->x2 != GTK_VALUE_DOUBLE (*arg)) { + ruler->x2 = GTK_VALUE_DOUBLE (*arg); + calc_bounds = TRUE; + } + break; + + case ARG_Y2: + if (ruler->y2 != GTK_VALUE_DOUBLE (*arg)) { + ruler->y2 = GTK_VALUE_DOUBLE (*arg); + calc_bounds = TRUE; + } + break; + + case ARG_FRAMES_PER_UNIT: + if (ruler->frames_per_unit != GTK_VALUE_LONG(*arg)) { + ruler->frames_per_unit = GTK_VALUE_LONG(*arg); + redraw = TRUE; + } + break; + + case ARG_FILL_COLOR: + if (ruler->fill_color != GTK_VALUE_INT(*arg)) { + ruler->fill_color = GTK_VALUE_INT(*arg); + redraw = TRUE; + } + break; + + case ARG_TICK_COLOR: + if (ruler->tick_color != GTK_VALUE_INT(*arg)) { + ruler->tick_color = GTK_VALUE_INT(*arg); + redraw = TRUE; + } + break; + + default: + break; + } + + if (calc_bounds) { + gtk_canvas_ruler_reset_bounds (item); + } + + if (redraw) { + gtk_canvas_item_request_update (item); + } + +} + +static void +gtk_canvas_ruler_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GtkCanvasRuler *ruler; + + ruler = GTK_CANVAS_RULER (object); + + switch (arg_id) { + case ARG_X1: + GTK_VALUE_DOUBLE (*arg) = ruler->x1; + break; + case ARG_Y1: + GTK_VALUE_DOUBLE (*arg) = ruler->y1; + break; + case ARG_X2: + GTK_VALUE_DOUBLE (*arg) = ruler->x2; + break; + case ARG_Y2: + GTK_VALUE_DOUBLE (*arg) = ruler->y2; + break; + case ARG_FRAMES_PER_UNIT: + GTK_VALUE_LONG (*arg) = ruler->frames_per_unit; + break; + case ARG_FILL_COLOR: + GTK_VALUE_INT (*arg) = ruler->fill_color; + break; + case ARG_TICK_COLOR: + GTK_VALUE_INT (*arg) = ruler->tick_color; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +gtk_canvas_ruler_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + GtkCanvasRuler *ruler; + double x; + double y; + + ruler = GTK_CANVAS_RULER (item); + + if (parent_class->update) + (* parent_class->update) (item, affine, clip_path, flags); + + gtk_canvas_ruler_reset_bounds (item); + + x = ruler->x1; + y = ruler->y1; + + gtk_canvas_item_i2w (item, &x, &y); + gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &ruler->bbox_ulx, &ruler->bbox_uly); + + x = ruler->x2; + y = ruler->y2; + + gtk_canvas_item_i2w (item, &x, &y); + gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &ruler->bbox_lrx, &ruler->bbox_lry); + + UINT_TO_RGB (ruler->tick_color, &ruler->tick_r, &ruler->tick_g, &ruler->tick_b); + UINT_TO_RGB (ruler->fill_color, &ruler->fill_r, &ruler->fill_g, &ruler->fill_b); +} + +static void +gtk_canvas_ruler_render (GtkCanvasItem *item, + GtkCanvasBuf *buf) +{ + GtkCanvasRuler *ruler; + int end, begin; + + ruler = GTK_CANVAS_RULER (item); + + if (parent_class->render) { + (*parent_class->render) (item, buf); + } + + if (buf->is_bg) { + gtk_canvas_buf_ensure_buf (buf); + buf->is_bg = FALSE; + } + + begin = MAX(ruler->bbox_ulx,buf->rect.x0); + + if (ruler->bbox_lrx >= 0) { + end = MIN(ruler->bbox_lrx,buf->rect.x1); + } else { + end = buf->rect.x1; + } + + if (begin == end) { + return; + } + + PAINT_BOX (buf, ruler->fill_r, ruler->fill_g, ruler->fill_b, 255, begin, ruler->bbox_uly, end, ruler->bbox_lry - 1); + PAINT_HORIZ (buf, ruler->tick_r, ruler->tick_g, ruler->tick_b, begin, end, ruler->bbox_lry - 1); +} + +static void +gtk_canvas_ruler_draw (GtkCanvasItem *item, + GdkDrawable *drawable, + int x, int y, + int width, int height) +{ + GtkCanvasRuler *ruler; + + ruler = GTK_CANVAS_RULER (item); + + if (parent_class->draw) { + (* parent_class->draw) (item, drawable, x, y, width, height); + } + + fprintf (stderr, "please don't use the CanvasRuler item in a non-aa Canvas\n"); + abort (); +} + +static void +gtk_canvas_ruler_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2) +{ + GtkCanvasRuler *ruler = GTK_CANVAS_RULER (item); + + *x1 = ruler->x1; + *y1 = ruler->y1; + *x2 = ruler->x2; + *y2 = ruler->y2; +} + +static double +gtk_canvas_ruler_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item) +{ + GtkCanvasRuler *ruler; + double x1, y1, x2, y2; + double dx, dy; + + ruler = GTK_CANVAS_RULER (item); + + *actual_item = item; + + /* Find the bounds for the rectangle plus its outline width */ + + gtk_canvas_ruler_bounds (item, &x1, &y1, &x2, &y2); + + /* Is point inside rectangle */ + + if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) { + return 0.0; + } + + /* Point is outside rectangle */ + + if (x < x1) + dx = x1 - x; + else if (x > x2) + dx = x - x2; + else + dx = 0.0; + + if (y < y1) + dy = y1 - y; + else if (y > y2) + dy = y - y2; + else + dy = 0.0; + + return sqrt (dx * dx + dy * dy); +} diff --git a/gtk2_ardour/canvas-ruler.h b/gtk2_ardour/canvas-ruler.h new file mode 100644 index 0000000000..db9937000a --- /dev/null +++ b/gtk2_ardour/canvas-ruler.h @@ -0,0 +1,68 @@ +/* gtk-canvas-ruler.h: GtkCanvas item for simple rects + * + * Copyright (C) 2001 Paul Davis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef __GTK_CANVAS_RULER_H__ +#define __GTK_CANVAS_RULER_H__ + +#include + +#include +#include "gtk-canvas/gtk-canvas.h" + +BEGIN_GTK_CANVAS_DECLS + +/* Wave viewer item for canvas. + */ + +#define GTK_CANVAS_TYPE_CANVAS_RULER (gtk_canvas_ruler_get_type ()) +#define GTK_CANVAS_RULER(obj) (GTK_CHECK_CAST ((obj), GTK_CANVAS_TYPE_CANVAS_RULER, GtkCanvasRuler)) +#define GTK_CANVAS_RULER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_CANVAS_TYPE_CANVAS_RULER, GtkCanvasRulerClass)) +#define GTK_CANVAS_IS_CANVAS_RULER(obj) (GTK_CHECK_TYPE ((obj), GTK_CANVAS_TYPE_CANVAS_RULER)) +#define GTK_CANVAS_IS_CANVAS_RULER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_CANVAS_TYPE_CANVAS_RULER)) + +typedef struct _GtkCanvasRuler GtkCanvasRuler; +typedef struct _GtkCanvasRulerClass GtkCanvasRulerClass; + +struct _GtkCanvasRuler +{ + GtkCanvasItem item; + double x1, y1, x2, y2; + uint32_t fill_color; + uint32_t tick_color; + uint32_t frames_per_unit; + + /* cached values set during update/used during render */ + + unsigned char fill_r, fill_b, fill_g, fill_a; + unsigned char tick_r, tick_b, tick_g; + guint32 bbox_ulx, bbox_uly; + guint32 bbox_lrx, bbox_lry; +}; + +struct _GtkCanvasRulerClass { + GtkCanvasItemClass parent_class; +}; + +GtkType gtk_canvas_ruler_get_type (void); + +END_GTK_CANVAS_DECLS + +#endif /* __GTK_CANVAS_RULER_H__ */ diff --git a/gtk2_ardour/canvas-simpleline.c b/gtk2_ardour/canvas-simpleline.c new file mode 100644 index 0000000000..9823975eee --- /dev/null +++ b/gtk2_ardour/canvas-simpleline.c @@ -0,0 +1,371 @@ +#include +#include +#include + +#include "canvas-simpleline.h" +#include "rgb_macros.h" + +enum { + ARG_0, + ARG_X1, + ARG_Y1, + ARG_X2, + ARG_Y2, + ARG_COLOR_RGBA +}; + +static void gtk_canvas_simpleline_class_init (GtkCanvasSimpleLineClass *class); +static void gtk_canvas_simpleline_init (GtkCanvasSimpleLine *simpleline); +static void gtk_canvas_simpleline_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void gtk_canvas_simpleline_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); + +static void gtk_canvas_simpleline_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags); +static void gtk_canvas_simpleline_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2); +static double gtk_canvas_simpleline_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item); +static void gtk_canvas_simpleline_render (GtkCanvasItem *item, GtkCanvasBuf *buf); +static void gtk_canvas_simpleline_draw (GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h); + +static GtkCanvasItemClass *parent_class; + + +GtkType +gtk_canvas_simpleline_get_type (void) +{ + static GtkType simpleline_type = 0; + + if (!simpleline_type) { + GtkTypeInfo simpleline_info = { + "GtkCanvasSimpleLine", + sizeof (GtkCanvasSimpleLine), + sizeof (GtkCanvasSimpleLineClass), + (GtkClassInitFunc) gtk_canvas_simpleline_class_init, + (GtkObjectInitFunc) gtk_canvas_simpleline_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + simpleline_type = gtk_type_unique (gtk_canvas_item_get_type (), &simpleline_info); + } + + return simpleline_type; +} + +static void +gtk_canvas_simpleline_class_init (GtkCanvasSimpleLineClass *class) +{ + GtkObjectClass *object_class; + GtkCanvasItemClass *item_class; + + object_class = (GtkObjectClass *) class; + item_class = (GtkCanvasItemClass *) class; + + parent_class = gtk_type_class (gtk_canvas_item_get_type ()); + + gtk_object_add_arg_type ("GtkCanvasSimpleLine::x1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X1); + gtk_object_add_arg_type ("GtkCanvasSimpleLine::y1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y1); + gtk_object_add_arg_type ("GtkCanvasSimpleLine::x2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X2); + gtk_object_add_arg_type ("GtkCanvasSimpleLine::y2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y2); + gtk_object_add_arg_type ("GtkCanvasSimpleLine::color_rgba", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_COLOR_RGBA); + + object_class->set_arg = gtk_canvas_simpleline_set_arg; + object_class->get_arg = gtk_canvas_simpleline_get_arg; + + item_class->update = gtk_canvas_simpleline_update; + item_class->bounds = gtk_canvas_simpleline_bounds; + item_class->point = gtk_canvas_simpleline_point; + item_class->render = gtk_canvas_simpleline_render; + item_class->draw = gtk_canvas_simpleline_draw; +} + +static void +gtk_canvas_simpleline_init (GtkCanvasSimpleLine *simpleline) +{ + simpleline->x1 = 0.0; + simpleline->y1 = 0.0; + simpleline->x2 = 0.0; + simpleline->y2 = 0.0; + simpleline->color = RGBA_TO_UINT(98,123,174,241); + simpleline->horizontal = TRUE; /* reset in the _update() method */ + GTK_CANVAS_ITEM(simpleline)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW; +} + +static void +gtk_canvas_simpleline_bounds_world (GtkCanvasItem *item, int* ix1, int* iy1, int* ix2, int* iy2) +{ + double x1, x2, y1, y2; + ArtPoint i1, i2; + ArtPoint w1, w2; + double i2w[6]; + GtkCanvasSimpleLine *simpleline = GTK_CANVAS_SIMPLELINE(item); + + gtk_canvas_simpleline_bounds (item, &x1, &y1, &x2, &y2); + + i1.x = x1; + i1.y = y1; + i2.x = x2; + i2.y = y2; + + gtk_canvas_item_i2w_affine (item, i2w); + art_affine_point (&w1, &i1, i2w); + art_affine_point (&w2, &i2, i2w); + + *ix1 = (int) rint(w1.x); + *ix2 = (int) rint(w2.x); + *iy1 = (int) rint(w1.y); + *iy2 = (int) rint(w2.y); + + /* the update rect has to be of non-zero width and height */ + + if (x1 == x2) { + simpleline->horizontal = FALSE; + *ix2 += 1; + } else { + simpleline->horizontal = TRUE; + *iy2 += 1; + } +} + +static void +gtk_canvas_simpleline_reset_bounds (GtkCanvasItem *item) +{ + int Ix1, Ix2, Iy1, Iy2; + + gtk_canvas_simpleline_bounds_world (item, &Ix1, &Iy1, &Ix2, &Iy2); + gtk_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2); +} + +/* + * CANVAS CALLBACKS + */ + +static void +gtk_canvas_simpleline_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GtkCanvasItem *item; + GtkCanvasSimpleLine *simpleline; + int redraw; + int calc_bounds; + + item = GTK_CANVAS_ITEM (object); + simpleline = GTK_CANVAS_SIMPLELINE (object); + + redraw = FALSE; + calc_bounds = FALSE; + + switch (arg_id) { + case ARG_X1: + if (simpleline->x1 != GTK_VALUE_DOUBLE (*arg)) { + simpleline->x1 = GTK_VALUE_DOUBLE (*arg); + calc_bounds = TRUE; + } + break; + + case ARG_Y1: + if (simpleline->y1 != GTK_VALUE_DOUBLE (*arg)) { + simpleline->y1 = GTK_VALUE_DOUBLE (*arg); + calc_bounds = TRUE; + } + break; + + case ARG_X2: + if (simpleline->x2 != GTK_VALUE_DOUBLE (*arg)) { + simpleline->x2 = GTK_VALUE_DOUBLE (*arg); + calc_bounds = TRUE; + } + break; + + case ARG_Y2: + if (simpleline->y2 != GTK_VALUE_DOUBLE (*arg)) { + simpleline->y2 = GTK_VALUE_DOUBLE (*arg); + calc_bounds = TRUE; + } + break; + + case ARG_COLOR_RGBA: + if (simpleline->color != GTK_VALUE_INT(*arg)) { + simpleline->color = GTK_VALUE_INT(*arg); + UINT_TO_RGBA (simpleline->color, &simpleline->r, &simpleline->g, &simpleline->b, &simpleline->a); + redraw = TRUE; + } + break; + + default: + break; + } + + if (calc_bounds) { + + gtk_canvas_item_request_update (item); + + } else if (redraw) { + + int Ix1, Ix2, Iy1, Iy2; + gtk_canvas_simpleline_bounds_world (item, &Ix1, &Iy1, &Ix2, &Iy2); + gtk_canvas_request_redraw (item->canvas, Ix1, Iy1, Ix2, Iy2); + } +} + +static void +gtk_canvas_simpleline_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GtkCanvasSimpleLine *simpleline; + + simpleline = GTK_CANVAS_SIMPLELINE (object); + + switch (arg_id) { + case ARG_X1: + GTK_VALUE_DOUBLE (*arg) = simpleline->x1; + break; + case ARG_Y1: + GTK_VALUE_DOUBLE (*arg) = simpleline->y1; + break; + case ARG_X2: + GTK_VALUE_DOUBLE (*arg) = simpleline->x2; + break; + case ARG_Y2: + GTK_VALUE_DOUBLE (*arg) = simpleline->y2; + break; + case ARG_COLOR_RGBA: + GTK_VALUE_INT (*arg) = simpleline->color; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +gtk_canvas_simpleline_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + GtkCanvasSimpleLine *simpleline; + double x; + double y; + + simpleline = GTK_CANVAS_SIMPLELINE (item); + + if (parent_class->update) + (* parent_class->update) (item, affine, clip_path, flags); + + gtk_canvas_simpleline_reset_bounds (item); + + x = simpleline->x1; + y = simpleline->y1; + + gtk_canvas_item_i2w (item, &x, &y); + gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &simpleline->bbox_ulx, &simpleline->bbox_uly); + + x = simpleline->x2; + y = simpleline->y2; + + gtk_canvas_item_i2w (item, &x, &y); + gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &simpleline->bbox_lrx, &simpleline->bbox_lry); +} + +static void +gtk_canvas_simpleline_render (GtkCanvasItem *item, + GtkCanvasBuf *buf) +{ + GtkCanvasSimpleLine *simpleline; + int end, begin; + + simpleline = GTK_CANVAS_SIMPLELINE (item); + + if (parent_class->render) { + (*parent_class->render) (item, buf); + } + + if (buf->is_bg) { + gtk_canvas_buf_ensure_buf (buf); + buf->is_bg = FALSE; + } + + // begin = MAX(simpleline->bbox_ulx,buf->rect.x0); + // end = MIN(simpleline->bbox_lrx,buf->rect.x1); + + begin = simpleline->bbox_ulx; + end = simpleline->bbox_lrx; + + if (simpleline->color != 0) { + if (simpleline->horizontal) { + PAINT_HORIZA(buf, simpleline->r, simpleline->g, simpleline->b, simpleline->a, + begin, end, simpleline->bbox_uly); + } else { + PAINT_VERTA(buf, simpleline->r, simpleline->g, simpleline->b, simpleline->a, + begin, simpleline->bbox_uly, simpleline->bbox_lry); + } + } +} + +static void +gtk_canvas_simpleline_draw (GtkCanvasItem *item, + GdkDrawable *drawable, + int x, int y, + int width, int height) +{ + GtkCanvasSimpleLine *simpleline; + + simpleline = GTK_CANVAS_SIMPLELINE (item); + + if (parent_class->draw) { + (* parent_class->draw) (item, drawable, x, y, width, height); + } + + fprintf (stderr, "please don't use the CanvasSimpleLine item in a non-aa Canvas\n"); + abort (); +} + +static void +gtk_canvas_simpleline_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2) +{ + GtkCanvasSimpleLine *simpleline = GTK_CANVAS_SIMPLELINE (item); + + *x1 = simpleline->x1; + *y1 = simpleline->y1; + *x2 = simpleline->x2; + *y2 = simpleline->y2; +} + +static double +gtk_canvas_simpleline_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item) +{ + GtkCanvasSimpleLine *simpleline; + double x1, y1, x2, y2; + double dx, dy; + + simpleline = GTK_CANVAS_SIMPLELINE (item); + + *actual_item = item; + + /* Find the bounds for the rectangle plus its outline width */ + + gtk_canvas_simpleline_bounds (item, &x1, &y1, &x2, &y2); + + /* Is point inside rectangle */ + + if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) { + return 0.0; + } + + /* Point is outside rectangle */ + + if (x < x1) + dx = x1 - x; + else if (x > x2) + dx = x - x2; + else + dx = 0.0; + + if (y < y1) + dy = y1 - y; + else if (y > y2) + dy = y - y2; + else + dy = 0.0; + + return sqrt (dx * dx + dy * dy); +} diff --git a/gtk2_ardour/canvas-simpleline.h b/gtk2_ardour/canvas-simpleline.h new file mode 100644 index 0000000000..f46f54d828 --- /dev/null +++ b/gtk2_ardour/canvas-simpleline.h @@ -0,0 +1,66 @@ +/* gtk-canvas-simpleline.h: GtkCanvas item for simple rects + * + * Copyright (C) 2001 Paul Davis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef __GTK_CANVAS_SIMPLELINE_H__ +#define __GTK_CANVAS_SIMPLELINE_H__ + +#include + +#include +#include "gtk-canvas/gtk-canvas.h" + +BEGIN_GTK_CANVAS_DECLS + +/* Wave viewer item for canvas. + */ + +#define GTK_CANVAS_TYPE_CANVAS_SIMPLELINE (gtk_canvas_simpleline_get_type ()) +#define GTK_CANVAS_SIMPLELINE(obj) (GTK_CHECK_CAST ((obj), GTK_CANVAS_TYPE_CANVAS_SIMPLELINE, GtkCanvasSimpleLine)) +#define GTK_CANVAS_SIMPLELINE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_CANVAS_TYPE_CANVAS_SIMPLELINE, GtkCanvasSimpleLineClass)) +#define GTK_CANVAS_IS_CANVAS_SIMPLELINE(obj) (GTK_CHECK_TYPE ((obj), GTK_CANVAS_TYPE_CANVAS_SIMPLELINE)) +#define GTK_CANVAS_IS_CANVAS_SIMPLELINE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_CANVAS_TYPE_CANVAS_SIMPLELINE)) + +typedef struct _GtkCanvasSimpleLine GtkCanvasSimpleLine; +typedef struct _GtkCanvasSimpleLineClass GtkCanvasSimpleLineClass; + +struct _GtkCanvasSimpleLine +{ + GtkCanvasItem item; + double x1, y1, x2, y2; + uint32_t color; + gboolean horizontal; + + /* cached values set during update/used during render */ + + unsigned char r, b, g, a; + guint32 bbox_ulx, bbox_uly; + guint32 bbox_lrx, bbox_lry; +}; + +struct _GtkCanvasSimpleLineClass { + GtkCanvasItemClass parent_class; +}; + +GtkType gtk_canvas_simpleline_get_type (void); + +END_GTK_CANVAS_DECLS + +#endif /* __GTK_CANVAS_SIMPLELINE_H__ */ diff --git a/gtk2_ardour/canvas-simplerect.c b/gtk2_ardour/canvas-simplerect.c new file mode 100644 index 0000000000..4ee4985a2c --- /dev/null +++ b/gtk2_ardour/canvas-simplerect.c @@ -0,0 +1,587 @@ +#include +#include +#include + +#include "canvas-simplerect.h" +#include "rgb_macros.h" + +enum { + ARG_0, + ARG_X1, + ARG_Y1, + ARG_X2, + ARG_Y2, + ARG_OUTLINE_PIXELS, + ARG_OUTLINE_WHAT, + ARG_FILL, + ARG_FILL_COLOR_RGBA, + ARG_OUTLINE_COLOR_RGBA, + ARG_DRAW + +}; + +static void gtk_canvas_simplerect_class_init (GtkCanvasSimpleRectClass *class); +static void gtk_canvas_simplerect_init (GtkCanvasSimpleRect *simplerect); +static void gtk_canvas_simplerect_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void gtk_canvas_simplerect_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); + +static void gtk_canvas_simplerect_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags); +static void gtk_canvas_simplerect_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2); +static double gtk_canvas_simplerect_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item); +static void gtk_canvas_simplerect_render (GtkCanvasItem *item, GtkCanvasBuf *buf); +static void gtk_canvas_simplerect_draw (GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h); + +static GtkCanvasItemClass *parent_class; + + +GtkType +gtk_canvas_simplerect_get_type (void) +{ + static GtkType simplerect_type = 0; + + if (!simplerect_type) { + GtkTypeInfo simplerect_info = { + "GtkCanvasSimpleRect", + sizeof (GtkCanvasSimpleRect), + sizeof (GtkCanvasSimpleRectClass), + (GtkClassInitFunc) gtk_canvas_simplerect_class_init, + (GtkObjectInitFunc) gtk_canvas_simplerect_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + simplerect_type = gtk_type_unique (gtk_canvas_item_get_type (), &simplerect_info); + } + + return simplerect_type; +} + +static void +gtk_canvas_simplerect_class_init (GtkCanvasSimpleRectClass *class) +{ + GtkObjectClass *object_class; + GtkCanvasItemClass *item_class; + + object_class = (GtkObjectClass *) class; + item_class = (GtkCanvasItemClass *) class; + + parent_class = gtk_type_class (gtk_canvas_item_get_type ()); + + gtk_object_add_arg_type ("GtkCanvasSimpleRect::x1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X1); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::y1", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y1); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::x2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X2); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::y2", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y2); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::fill", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_FILL); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::draw", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DRAW); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::fill_color_rgba", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_FILL_COLOR_RGBA); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::outline_color_rgba", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_COLOR_RGBA); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::outline_pixels", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_PIXELS); + gtk_object_add_arg_type ("GtkCanvasSimpleRect::outline_what", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_OUTLINE_WHAT); + + object_class->set_arg = gtk_canvas_simplerect_set_arg; + object_class->get_arg = gtk_canvas_simplerect_get_arg; + + item_class->update = gtk_canvas_simplerect_update; + item_class->bounds = gtk_canvas_simplerect_bounds; + item_class->point = gtk_canvas_simplerect_point; + item_class->render = gtk_canvas_simplerect_render; + item_class->draw = gtk_canvas_simplerect_draw; +} + +static void +gtk_canvas_simplerect_init (GtkCanvasSimpleRect *simplerect) +{ + simplerect->x1 = 0.0; + simplerect->y1 = 0.0; + simplerect->x2 = 0.0; + simplerect->y2 = 0.0; + simplerect->fill = TRUE; + simplerect->draw = TRUE; + simplerect->full_draw_on_update = TRUE; + simplerect->fill_color = 0; + simplerect->outline_color = 0; + simplerect->outline_pixels = 1; + simplerect->outline_what = 0xf; + + GTK_CANVAS_ITEM(simplerect)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW; +} + +static void +gtk_canvas_simplerect_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2) +{ + GtkCanvasSimpleRect *simplerect = GTK_CANVAS_SIMPLERECT (item); + + *x1 = simplerect->x1; + *y1 = simplerect->y1; + *x2 = simplerect->x2 + 1; + *y2 = simplerect->y2 + 1; + +} + +static void +gtk_canvas_simplerect_reset_bounds (GtkCanvasItem *item) +{ + GtkCanvasSimpleRect* simplerect; + double x1, x2, y1, y2; + double old_x1, old_x2, old_y1, old_y2; + double a, b; + + old_x1 = item->x1; + old_y1 = item->y1; + old_x2 = item->x2; + old_y2 = item->y2; + + gtk_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2); + gtk_canvas_item_i2w (item, &x1, &y1); + gtk_canvas_item_i2w (item, &x2, &y2); + + item->x1 = x1; + item->y1 = y1; + item->x2 = x2; + item->y2 = y2; + + /* now compute bounding box in canvas units */ + + simplerect = GTK_CANVAS_SIMPLERECT (item); + + gtk_canvas_w2c (GTK_CANVAS(item->canvas), x1, y1, &simplerect->bbox_ulx, &simplerect->bbox_uly); + gtk_canvas_w2c (GTK_CANVAS(item->canvas), x2, y2, &simplerect->bbox_lrx, &simplerect->bbox_lry); + + /* now queue redraws for changed areas */ + + if (item->x1 != old_x1) { + + /* left edge changed. redraw the area that altered */ + + a = MIN(item->x1, old_x1); + b = MAX(item->x1, old_x1); + gtk_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2); + } + + if (item->x2 != old_x2) { + + /* right edge changed. redraw the area that altered */ + + a = MIN(item->x2, old_x2); + b = MAX(item->x2, old_x2); + gtk_canvas_request_redraw (item->canvas, a - 1, item->y1, b + 1, item->y2); + } + + if (item->y1 != old_y1) { + + /* top edge changed. redraw the area that altered */ + + a = MIN(item->y1, old_y1); + b = MAX(item->y1, old_y1); + gtk_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1); + } + + if (item->y2 != old_y2) { + + /* lower edge changed. redraw the area that altered */ + + a = MIN(item->y2, old_y2); + b = MAX(item->y2, old_y2); + gtk_canvas_request_redraw (item->canvas, item->x1, a - 1, item->x2, b + 1); + } +} + +/* + * CANVAS CALLBACKS + */ + +static void +gtk_canvas_simplerect_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GtkCanvasItem *item; + GtkCanvasSimpleRect *simplerect; + int update; + int bounds_changed; + + item = GTK_CANVAS_ITEM (object); + simplerect = GTK_CANVAS_SIMPLERECT (object); + + update = FALSE; + bounds_changed = FALSE; + + switch (arg_id) { + case ARG_X1: + if (simplerect->x1 != GTK_VALUE_DOUBLE (*arg)) { + simplerect->x1 = GTK_VALUE_DOUBLE (*arg); + bounds_changed = TRUE; + } + break; + + case ARG_Y1: + if (simplerect->y1 != GTK_VALUE_DOUBLE (*arg)) { + simplerect->y1 = GTK_VALUE_DOUBLE (*arg); + bounds_changed = TRUE; + } + break; + + case ARG_X2: + if (simplerect->x2 != GTK_VALUE_DOUBLE (*arg)) { + simplerect->x2 = GTK_VALUE_DOUBLE (*arg); + bounds_changed = TRUE; + } + break; + + case ARG_Y2: + if (simplerect->y2 != GTK_VALUE_DOUBLE (*arg)) { + simplerect->y2 = GTK_VALUE_DOUBLE (*arg); + bounds_changed = TRUE; + } + break; + + case ARG_DRAW: + if (simplerect->draw != GTK_VALUE_BOOL (*arg)) { + simplerect->draw = GTK_VALUE_BOOL (*arg); + update = TRUE; + } + break; + + + case ARG_FILL: + if (simplerect->fill != GTK_VALUE_BOOL (*arg)) { + simplerect->fill = GTK_VALUE_BOOL (*arg); + update = TRUE; + } + break; + + case ARG_FILL_COLOR_RGBA: + if (simplerect->fill_color != GTK_VALUE_INT(*arg)) { + simplerect->fill_color = GTK_VALUE_INT(*arg); + update = TRUE; + } + break; + + case ARG_OUTLINE_COLOR_RGBA: + if (simplerect->outline_color != GTK_VALUE_INT(*arg)) { + simplerect->outline_color = GTK_VALUE_INT(*arg); + update = TRUE; + } + break; + + case ARG_OUTLINE_PIXELS: + if (simplerect->outline_pixels != GTK_VALUE_INT(*arg)) { + simplerect->outline_pixels = GTK_VALUE_INT(*arg); + update = TRUE; + } + break; + + case ARG_OUTLINE_WHAT: + if (simplerect->outline_what != GTK_VALUE_INT(*arg)) { + simplerect->outline_what = GTK_VALUE_INT(*arg); + update = TRUE; + } + break; + + default: + break; + } + + simplerect->full_draw_on_update = update; + + if (update || bounds_changed) { + gtk_canvas_item_request_update (item); + } +} + +static void +gtk_canvas_simplerect_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GtkCanvasSimpleRect *simplerect; + + simplerect = GTK_CANVAS_SIMPLERECT (object); + + switch (arg_id) { + case ARG_X1: + GTK_VALUE_DOUBLE (*arg) = simplerect->x1; + break; + case ARG_Y1: + GTK_VALUE_DOUBLE (*arg) = simplerect->y1; + break; + case ARG_X2: + GTK_VALUE_DOUBLE (*arg) = simplerect->x2; + break; + case ARG_Y2: + GTK_VALUE_DOUBLE (*arg) = simplerect->y2; + break; + case ARG_DRAW: + GTK_VALUE_BOOL (*arg) = simplerect->draw; + break; + case ARG_FILL: + GTK_VALUE_BOOL (*arg) = simplerect->fill; + break; + case ARG_FILL_COLOR_RGBA: + GTK_VALUE_INT (*arg) = simplerect->fill_color; + break; + case ARG_OUTLINE_COLOR_RGBA: + GTK_VALUE_INT (*arg) = simplerect->outline_color; + break; + case ARG_OUTLINE_PIXELS: + GTK_VALUE_INT (*arg) = simplerect->outline_pixels; + break; + case ARG_OUTLINE_WHAT: + GTK_VALUE_INT (*arg) = simplerect->outline_what; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +gtk_canvas_simplerect_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + GtkCanvasSimpleRect *simplerect; + unsigned char foo; + + simplerect = GTK_CANVAS_SIMPLERECT (item); + + if (parent_class->update) + (* parent_class->update) (item, affine, clip_path, flags); + + gtk_canvas_simplerect_reset_bounds (item); + + if (simplerect->full_draw_on_update) { + gtk_canvas_request_redraw (item->canvas, + simplerect->bbox_ulx, + simplerect->bbox_uly, + simplerect->bbox_lrx+1, + simplerect->bbox_lry+1); + simplerect->full_draw_on_update = FALSE; + } + + UINT_TO_RGBA (simplerect->fill_color, &simplerect->fill_r, &simplerect->fill_g, &simplerect->fill_b, &simplerect->fill_a); + UINT_TO_RGBA (simplerect->outline_color, &simplerect->outline_r, &simplerect->outline_g, &simplerect->outline_b, &foo); +} + +#define SIMPLERECT_FAST_RENDERER +#ifdef SIMPLERECT_FAST_RENDERER + +static void +gtk_canvas_simplerect_render (GtkCanvasItem *item, + GtkCanvasBuf *buf) +{ + GtkCanvasSimpleRect *simplerect; + int end, begin; + int ey, sy; + unsigned int i; + ArtIRect intersection; + ArtIRect self; + + simplerect = GTK_CANVAS_SIMPLERECT (item); + + if (parent_class->render) { + (*parent_class->render) (item, buf); + } + + if (buf->is_bg) { + + // this can be useful for debugging/understanding how the canvas redraws + // stuff. + + // gint randr, randg, randb; + // randr = random() % 255; + // randg = random() % 255; + // randb = random() % 255; + // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1); + + gtk_canvas_buf_ensure_buf (buf); + buf->is_bg = FALSE; + } + + if (!simplerect->draw) { + return; + } + + self.x0 = simplerect->bbox_ulx; + self.y0 = simplerect->bbox_uly; + self.x1 = simplerect->bbox_lrx; + self.y1 = simplerect->bbox_lry; + + art_irect_intersect (&intersection, &self, &buf->rect); + + begin = MAX(simplerect->bbox_ulx, buf->rect.x0); + end = MIN((simplerect->bbox_lrx-1), buf->rect.x1); + + sy = simplerect->bbox_uly; + ey = simplerect->bbox_lry-1; + + if (simplerect->fill) { + + // this can be useful for debugging/understanding how the canvas redraws + // stuff. + + // gint randr, randg, randb; + // randr = random() % 255; + // randg = random() % 255; + // randb = random() % 255; + // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey); + + FAST_PAINT_BOX (buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a, + intersection.x0, intersection.y0, + intersection.x1, intersection.y1); + + } + + for (i = 0; i < simplerect->outline_pixels; ++i) { + + if (simplerect->outline_what & 0x1) { + if (begin == simplerect->bbox_ulx) { + PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey); + } + } + + if (simplerect->outline_what & 0x2) { + if (end == (simplerect->bbox_lrx - 1)) { + PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1); + } + } + + if (simplerect->outline_what & 0x4) { + PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i); + } + + if (simplerect->outline_what & 0x8) { + PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i); + } + } +} + +#else /* SIMPLERECT_FAST_RENDERER */ + +static void +gtk_canvas_simplerect_render (GtkCanvasItem *item, + GtkCanvasBuf *buf) +{ + GtkCanvasSimpleRect *simplerect; + int end, begin; + int ey, sy; + unsigned int i; + + simplerect = GTK_CANVAS_SIMPLERECT (item); + + if (parent_class->render) { + (*parent_class->render) (item, buf); + } + + if (buf->is_bg) { + + // this can be useful for debugging/understanding how the canvas redraws + // stuff. + + // gint randr, randg, randb; + // randr = random() % 255; + // randg = random() % 255; + // randb = random() % 255; + // PAINT_BOX(buf, randr, randg, randb, 255, buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1); + + gtk_canvas_buf_ensure_buf (buf); + buf->is_bg = FALSE; + } + + if (!simplerect->draw) { + return; + } + + begin = MAX(simplerect->bbox_ulx,buf->rect.x0); + end = MIN((simplerect->bbox_lrx-1),buf->rect.x1); + + sy = simplerect->bbox_uly; + ey = simplerect->bbox_lry-1; + + if (simplerect->fill) { + + // this can be useful for debugging/understanding how the canvas redraws + // stuff. + + // gint randr, randg, randb; + // randr = random() % 255; + // randg = random() % 255; + // randb = random() % 255; + // PAINT_BOX(buf, randr, randg, randb, simplerect->fill_a, begin, sy, end, ey); + + PAINT_BOX(buf, simplerect->fill_r, simplerect->fill_g, simplerect->fill_b, simplerect->fill_a, begin, sy, end, ey); + } + + for (i = 0; i < simplerect->outline_pixels; ++i) { + + if (simplerect->outline_what & 0x1) { + if (begin == simplerect->bbox_ulx) { + PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin + i, sy, ey); + } + } + + if (simplerect->outline_what & 0x2) { + if (end == (simplerect->bbox_lrx - 1)) { + PAINT_VERT(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, end - i, sy, ey + 1); + } + } + + if (simplerect->outline_what & 0x4) { + PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end, sy+i); + } + + if (simplerect->outline_what & 0x8) { + PAINT_HORIZ(buf, simplerect->outline_r, simplerect->outline_g, simplerect->outline_b, begin, end + 1, ey-i); + } + } +} +#endif /* SIMPLERECT_FAST_RENDERER */ + +static void +gtk_canvas_simplerect_draw (GtkCanvasItem *item, + GdkDrawable *drawable, + int x, int y, + int width, int height) +{ + fprintf (stderr, "please don't use the CanvasSimpleRect item in a non-aa Canvas\n"); + abort (); +} + +static double +gtk_canvas_simplerect_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item) +{ + GtkCanvasSimpleRect *simplerect; + double x1, y1, x2, y2; + double dx, dy; + + simplerect = GTK_CANVAS_SIMPLERECT (item); + + *actual_item = item; + + /* Find the bounds for the rectangle plus its outline width */ + + gtk_canvas_simplerect_bounds (item, &x1, &y1, &x2, &y2); + + /* Is point inside rectangle */ + + if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) { + return 0.0; + } + + /* Point is outside rectangle */ + + if (x < x1) + dx = x1 - x; + else if (x > x2) + dx = x - x2; + else + dx = 0.0; + + if (y < y1) + dy = y1 - y; + else if (y > y2) + dy = y - y2; + else + dy = 0.0; + + return sqrt (dx * dx + dy * dy); +} diff --git a/gtk2_ardour/canvas-simplerect.h b/gtk2_ardour/canvas-simplerect.h new file mode 100644 index 0000000000..f15cb40548 --- /dev/null +++ b/gtk2_ardour/canvas-simplerect.h @@ -0,0 +1,72 @@ +/* gtk-canvas-simplerect.h: GtkCanvas item for simple rects + * + * Copyright (C) 2001 Paul Davis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef __GTK_CANVAS_SIMPLERECT_H__ +#define __GTK_CANVAS_SIMPLERECT_H__ + +#include + +#include +#include "gtk-canvas/gtk-canvas.h" + +BEGIN_GTK_CANVAS_DECLS + +/* Wave viewer item for canvas. + */ + +#define GTK_CANVAS_TYPE_CANVAS_SIMPLERECT (gtk_canvas_simplerect_get_type ()) +#define GTK_CANVAS_SIMPLERECT(obj) (GTK_CHECK_CAST ((obj), GTK_CANVAS_TYPE_CANVAS_SIMPLERECT, GtkCanvasSimpleRect)) +#define GTK_CANVAS_SIMPLERECT_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_CANVAS_TYPE_CANVAS_SIMPLERECT, GtkCanvasSimpleRectClass)) +#define GTK_CANVAS_IS_CANVAS_SIMPLERECT(obj) (GTK_CHECK_TYPE ((obj), GTK_CANVAS_TYPE_CANVAS_SIMPLERECT)) +#define GTK_CANVAS_IS_CANVAS_SIMPLERECT_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_CANVAS_TYPE_CANVAS_SIMPLERECT)) + +typedef struct _GtkCanvasSimpleRect GtkCanvasSimpleRect; +typedef struct _GtkCanvasSimpleRectClass GtkCanvasSimpleRectClass; + +struct _GtkCanvasSimpleRect +{ + GtkCanvasItem item; + double x1, y1, x2, y2; + gboolean fill; + gboolean draw; + gboolean full_draw_on_update; + uint32_t fill_color; + uint32_t outline_color; + uint32_t outline_pixels; + + /* cached values set during update/used during render */ + + unsigned char fill_r, fill_b, fill_g, fill_a; + unsigned char outline_r, outline_b, outline_g; + unsigned char outline_what; + guint32 bbox_ulx, bbox_uly; + guint32 bbox_lrx, bbox_lry; +}; + +struct _GtkCanvasSimpleRectClass { + GtkCanvasItemClass parent_class; +}; + +GtkType gtk_canvas_simplerect_get_type (void); + +END_GTK_CANVAS_DECLS + +#endif /* __GTK_CANVAS_SIMPLERECT_H__ */ diff --git a/gtk2_ardour/canvas-waveview.c b/gtk2_ardour/canvas-waveview.c new file mode 100644 index 0000000000..ce46811d2c --- /dev/null +++ b/gtk2_ardour/canvas-waveview.c @@ -0,0 +1,1013 @@ +/* + Copyright (C) 2000-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include + +#include + +#include "canvas-waveview.h" +#include "rgb_macros.h" + +enum { + ARG_0, + ARG_DATA_SRC, + ARG_CHANNEL, + ARG_LENGTH_FUNCTION, + ARG_PEAK_FUNCTION, + ARG_GAIN_FUNCTION, + ARG_GAIN_SRC, + ARG_CACHE, + ARG_CACHE_UPDATER, + ARG_SAMPLES_PER_PIXEL, + ARG_AMPLITUDE_ABOVE_AXIS, + ARG_X, + ARG_Y, + ARG_HEIGHT, + ARG_WAVE_COLOR, + ARG_RECTIFIED, + ARG_SOURCEFILE_LENGTH_FUNCTION, + ARG_REGION_START +}; + +static void gtk_canvas_waveview_class_init (GtkCanvasWaveViewClass *class); +static void gtk_canvas_waveview_init (GtkCanvasWaveView *waveview); +static void gtk_canvas_waveview_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void gtk_canvas_waveview_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); + +static void gtk_canvas_waveview_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags); +static void gtk_canvas_waveview_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2); +static double gtk_canvas_waveview_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item); + +static void gtk_canvas_waveview_render (GtkCanvasItem *item, GtkCanvasBuf *buf); +static void gtk_canvas_waveview_draw (GtkCanvasItem *item, GdkDrawable *drawable, int x, int y, int w, int h); + +static void gtk_canvas_waveview_set_data_src (GtkCanvasWaveView *, void *); +static void gtk_canvas_waveview_set_channel (GtkCanvasWaveView *, guint32); + +static gint32 gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_sample, gulong end_sample); + +static GtkCanvasItemClass *parent_class; + +GtkType +gtk_canvas_waveview_get_type (void) +{ + static GtkType waveview_type = 0; + + if (!waveview_type) { + GtkTypeInfo waveview_info = { + "GtkCanvasWaveView", + sizeof (GtkCanvasWaveView), + sizeof (GtkCanvasWaveViewClass), + (GtkClassInitFunc) gtk_canvas_waveview_class_init, + (GtkObjectInitFunc) gtk_canvas_waveview_init, + NULL, /* reserved_1 */ + NULL, /* reserved_2 */ + (GtkClassInitFunc) NULL + }; + + waveview_type = gtk_type_unique (gtk_canvas_item_get_type (), &waveview_info); + } + + return waveview_type; +} + +static void +gtk_canvas_waveview_class_init (GtkCanvasWaveViewClass *class) +{ + GtkObjectClass *object_class; + GtkCanvasItemClass *item_class; + + object_class = (GtkObjectClass *) class; + item_class = (GtkCanvasItemClass *) class; + + parent_class = gtk_type_class (gtk_canvas_item_get_type ()); + + gtk_object_add_arg_type ("GtkCanvasWaveView::data_src", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_DATA_SRC); + gtk_object_add_arg_type ("GtkCanvasWaveView::channel", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_CHANNEL); + gtk_object_add_arg_type ("GtkCanvasWaveView::length_function", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_LENGTH_FUNCTION); + gtk_object_add_arg_type ("GtkCanvasWaveView::sourcefile_length_function", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_SOURCEFILE_LENGTH_FUNCTION); + gtk_object_add_arg_type ("GtkCanvasWaveView::peak_function", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_PEAK_FUNCTION); + gtk_object_add_arg_type ("GtkCanvasWaveView::gain_function", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_GAIN_FUNCTION); + gtk_object_add_arg_type ("GtkCanvasWaveView::gain_src", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_GAIN_SRC); + gtk_object_add_arg_type ("GtkCanvasWaveView::cache", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_CACHE); + gtk_object_add_arg_type ("GtkCanvasWaveView::cache_updater", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_CACHE_UPDATER); + gtk_object_add_arg_type ("GtkCanvasWaveView::samples_per_unit", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_SAMPLES_PER_PIXEL); + gtk_object_add_arg_type ("GtkCanvasWaveView::amplitude_above_axis", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_AMPLITUDE_ABOVE_AXIS); + gtk_object_add_arg_type ("GtkCanvasWaveView::x", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X); + gtk_object_add_arg_type ("GtkCanvasWaveView::y", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y); + gtk_object_add_arg_type ("GtkCanvasWaveView::height", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_HEIGHT); + gtk_object_add_arg_type ("GtkCanvasWaveView::wave_color", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_WAVE_COLOR); + gtk_object_add_arg_type ("GtkCanvasWaveView::rectified", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_RECTIFIED); + gtk_object_add_arg_type ("GtkCanvasWaveView::region_start", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_REGION_START); + + object_class->set_arg = gtk_canvas_waveview_set_arg; + object_class->get_arg = gtk_canvas_waveview_get_arg; + + item_class->update = gtk_canvas_waveview_update; + item_class->bounds = gtk_canvas_waveview_bounds; + item_class->point = gtk_canvas_waveview_point; + item_class->render = gtk_canvas_waveview_render; + item_class->draw = gtk_canvas_waveview_draw; +} + +GtkCanvasWaveViewCache* +gtk_canvas_waveview_cache_new () +{ + GtkCanvasWaveViewCache *c; + + c = g_malloc (sizeof (GtkCanvasWaveViewCache)); + + c->allocated = 2048; + c->data = g_malloc (sizeof (GtkCanvasWaveViewCacheEntry) * c->allocated); + c->data_size = 0; + c->start = 0; + c->end = 0; + + return c; +} + +void +gtk_canvas_waveview_cache_destroy (GtkCanvasWaveViewCache* cache) +{ + g_free (cache->data); + g_free (cache); +} + +static void +gtk_canvas_waveview_init (GtkCanvasWaveView *waveview) +{ + waveview->x = 0.0; + waveview->y = 0.0; + waveview->cache = 0; + waveview->cache_updater = FALSE; + waveview->data_src = NULL; + waveview->channel = 0; + waveview->peak_function = NULL; + waveview->length_function = NULL; + waveview->sourcefile_length_function = NULL; + waveview->gain_curve_function = NULL; + waveview->gain_src = NULL; + waveview->rectified = FALSE; + waveview->region_start = 0; + waveview->samples_per_unit = 1.0; + waveview->amplitude_above_axis = 1.0; + waveview->height = 100.0; + waveview->screen_width = gdk_screen_width (); + waveview->reload_cache_in_render = FALSE; + + waveview->wave_color = RGBA_TO_UINT(44,35,126,255); + + GTK_CANVAS_ITEM(waveview)->object.flags |= GTK_CANVAS_ITEM_NO_AUTO_REDRAW; +} + +#define DEBUG_CACHE 0 + +static gint32 +gtk_canvas_waveview_ensure_cache (GtkCanvasWaveView *waveview, gulong start_sample, gulong end_sample) +{ + gulong required_cache_entries; + gulong rf1, rf2,rf3, required_frames; + gulong new_cache_start, new_cache_end; + gulong half_width; + gulong npeaks; + gulong offset; + gulong ostart; + gulong present_frames; + gulong present_entries; + gulong copied; + GtkCanvasWaveViewCache *cache; + float* gain; + + cache = waveview->cache; + + start_sample = start_sample + waveview->region_start; + end_sample = end_sample + waveview->region_start; +#if DEBUG_CACHE + // printf("waveview->region_start == %lu\n",waveview->region_start); + printf ("=> 0x%x cache @ 0x%x range: %lu - %lu request: %lu - %lu (%lu frames)\n", + waveview, cache, + cache->start, cache->end, + start_sample, end_sample, end_sample - start_sample); +#endif + + if (cache->start <= start_sample && cache->end >= end_sample) { +#if DEBUG_CACHE + // printf ("0x%x: cache hit for %lu-%lu (cache holds: %lu-%lu\n", + // waveview, start_sample, end_sample, cache->start, cache->end); +#endif + goto out; + } + + /* make sure the cache is at least twice as wide as the screen width, and put the start sample + in the middle, ensuring that we cover the end_sample. + */ + + /* Note the assumption that we have a 1:1 units:pixel ratio for the canvas. Its everywhere ... */ + + half_width = (gulong) floor ((waveview->screen_width * waveview->samples_per_unit)/2.0 + 0.5); + + if (start_sample < half_width) { + new_cache_start = 0; + } else { + new_cache_start = start_sample - half_width; + } + + /* figure out how many frames we want */ + + rf1 = end_sample - start_sample + 1; + rf2 = (gulong) floor ((waveview->screen_width * waveview->samples_per_unit * 2.0f)); + required_frames = MAX(rf1,rf2); + + /* but make sure it doesn't extend beyond the end of the source material */ + + rf3 = (gulong) (waveview->sourcefile_length_function (waveview->data_src)) + 1; + rf3 -= new_cache_start; + +#if DEBUG_CACHE + fprintf (stderr, "\n\nAVAILABLE FRAMES = %lu of %lu, start = %lu, sstart = %lu, cstart = %lu\n", + rf3, waveview->sourcefile_length_function (waveview->data_src), + waveview->region_start, start_sample, new_cache_start); +#endif + + required_frames = MIN(required_frames,rf3); + + new_cache_end = new_cache_start + required_frames - 1; + + required_cache_entries = (gulong) floor (required_frames / waveview->samples_per_unit ); + +#if DEBUG_CACHE + fprintf (stderr, "new cache = %lu - %lu\n", new_cache_start, new_cache_end); + fprintf(stderr,"required_cach_entries = %lu, samples_per_unit = %f\n", + required_cache_entries,waveview->samples_per_unit); +#endif + + if (required_cache_entries > cache->allocated) { + cache->data = g_realloc (cache->data, sizeof (GtkCanvasWaveViewCacheEntry) * required_cache_entries); + cache->allocated = required_cache_entries; + // cache->start = 0; + // cache->end = 0; + } + + ostart = new_cache_start; + +#undef CACHE_MEMMOVE_OPTIMIZATION +#ifdef CACHE_MEMMOVE_OPTIMIZATION + + /* data is not entirely in the cache, so go fetch it, making sure to fill the cache */ + + /* some of the required cache entries are in the cache, but in the wrong + locations. use memmove to fix this. + */ + + if (cache->start < new_cache_start && new_cache_start < cache->end) { + + /* case one: the common area is at the end of the existing cache. move it + to the beginning of the cache, and set up to refill whatever remains. + + + wv->cache_start wv->cache_end + |-------------------------------------------------------| cache + |--------------------------------| requested + <-------------------> + "present" + new_cache_start new_cache_end + */ + + + present_frames = cache->end - new_cache_start; + present_entries = (gulong) floor (present_frames / waveview->samples_per_unit); + +#if DEBUG_CACHE + fprintf (stderr, "existing material at end of current cache, move to start of new cache\n" + "\tcopy from %lu to start\n", cache->data_size - present_entries); +#endif + + memmove (&cache->data[0], + &cache->data[cache->data_size - present_entries], + present_entries * sizeof (GtkCanvasWaveViewCacheEntry)); + +#if DEBUG_CACHE + fprintf (stderr, "satisfied %lu of %lu frames, offset = %lu, will start at %lu (ptr = 0x%x)\n", + present_frames, required_frames, present_entries, new_cache_start + present_entries, + cache->data + present_entries); +#endif + + copied = present_entries; + offset = present_entries; + new_cache_start += present_frames; + required_frames -= present_frames; + + } else if (new_cache_end > cache->start && new_cache_end < cache->end) { + + /* case two: the common area lives at the beginning of the existing cache. + + wv->cache_start wv->cache_end + |-----------------------------------------------------| + |--------------------------------| + <-----------------> + "present" + + new_cache_start new_cache_end + */ + + present_frames = new_cache_end - cache->start; + present_entries = (gulong) floor (present_frames / waveview->samples_per_unit); + + memmove (&cache->data[cache->data_size - present_entries], + &cache->data[0], + present_entries * sizeof (GtkCanvasWaveViewCacheEntry)); + +#if DEBUG_CACHE + fprintf (stderr, "existing material at start of current cache, move to start of end cache\n"); +#endif + +#if DEBUG_CACHE + fprintf (stderr, "satisfied %lu of %lu frames, offset = %lu, will start at %lu (ptr = 0x%x)\n", + present_entries, required_frames, present_entries, new_cache_start + present_entries, + cache->data + present_entries); +#endif + + copied = present_entries; + offset = 0; + required_frames -= present_frames; + + + } else { + copied = 0; + offset = 0; + + } + +#else + copied = 0; + offset = 0; + +#endif /* CACHE_MEMMOVE_OPTIMIZATION */ + +// fprintf(stderr,"length == %lu\n",waveview->length_function (waveview->data_src)); +// required_frames = MIN (waveview->length_function (waveview->data_src) - new_cache_start, required_frames); + npeaks = (gulong) floor (required_frames / waveview->samples_per_unit); + npeaks = MAX (1, npeaks); + required_frames = npeaks * waveview->samples_per_unit; + +#if DEBUG_CACHE + + + printf ("requesting %lu/%f to cover %lu-%lu at %f spu (request was %lu-%lu) into cache + %lu\n", + required_frames, required_frames/waveview->samples_per_unit, new_cache_start, new_cache_end, + waveview->samples_per_unit, start_sample, end_sample, offset); +#endif + +#if DEBUG_CACHE +// printf ("cache holds %lu entries, requesting %lu to cover %lu-%lu (request was %lu-%lu)\n", +// cache->data_size, npeaks, new_cache_start, new_cache_end, +// start_sample, end_sample); +#endif + + waveview->peak_function (waveview->data_src, npeaks, new_cache_start, required_frames, cache->data + offset, waveview->channel,waveview->samples_per_unit); + + /* take into account any copied peaks */ + + npeaks += copied; + + if (npeaks < cache->allocated) { +#if DEBUG_CACHE + fprintf (stderr, "zero fill cache for %lu at %lu\n", cache->allocated - npeaks, npeaks); +#endif + memset (&cache->data[npeaks], 0, sizeof (GtkCanvasWaveViewCacheEntry) * (cache->allocated - npeaks)); + cache->data_size = npeaks; + } else { + cache->data_size = cache->allocated; + } + + if (waveview->gain_curve_function) { + guint32 n; + + gain = (float*) malloc (sizeof (float) * cache->data_size); + + waveview->gain_curve_function (waveview->gain_src, new_cache_start, new_cache_end, gain, cache->data_size); + + for (n = 0; n < cache->data_size; ++n) { + cache->data[n].min *= gain[n]; + cache->data[n].max *= gain[n]; + } + + free (gain); + + } + + cache->start = ostart; + cache->end = new_cache_end; + + out: +#if DEBUG_CACHE + fprintf (stderr, "return cache index = %d\n", + (gint32) floor ((((double) (start_sample - cache->start)) / waveview->samples_per_unit) + 0.5)); +#endif + return (gint32) floor ((((double) (start_sample - cache->start)) / waveview->samples_per_unit) + 0.5); + +} + +void +gtk_canvas_waveview_set_data_src (GtkCanvasWaveView *waveview, void *data_src) +{ + + if (waveview->cache_updater) { + if (waveview->data_src == data_src) { + waveview->reload_cache_in_render = TRUE; + return; + } + + waveview->cache->start = 0; + waveview->cache->end = 0; + } + + waveview->data_src = data_src; +} + +void +gtk_canvas_waveview_set_channel (GtkCanvasWaveView *waveview, guint32 chan) +{ + if (waveview->channel == chan) { + return; + } + + waveview->channel = chan; +} + +static void +gtk_canvas_waveview_reset_bounds (GtkCanvasItem *item) + +{ + double x1, x2, y1, y2; + ArtPoint i1, i2; + ArtPoint w1, w2; + int Ix1, Ix2, Iy1, Iy2; + double i2w[6]; + + gtk_canvas_waveview_bounds (item, &x1, &y1, &x2, &y2); + + i1.x = x1; + i1.y = y1; + i2.x = x2; + i2.y = y2; + + gtk_canvas_item_i2w_affine (item, i2w); + art_affine_point (&w1, &i1, i2w); + art_affine_point (&w2, &i2, i2w); + + Ix1 = (int) rint(w1.x); + Ix2 = (int) rint(w2.x); + Iy1 = (int) rint(w1.y); + Iy2 = (int) rint(w2.y); + + gtk_canvas_update_bbox (item, Ix1, Iy1, Ix2, Iy2); +} + +/* + * CANVAS CALLBACKS + */ + +static void +gtk_canvas_waveview_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GtkCanvasItem *item; + GtkCanvasWaveView *waveview; + int redraw; + int calc_bounds; + + item = GTK_CANVAS_ITEM (object); + waveview = GTK_CANVAS_WAVEVIEW (object); + + redraw = FALSE; + calc_bounds = FALSE; + + switch (arg_id) { + case ARG_DATA_SRC: + gtk_canvas_waveview_set_data_src (waveview, GTK_VALUE_POINTER(*arg)); + redraw = TRUE; + break; + + case ARG_CHANNEL: + gtk_canvas_waveview_set_channel (waveview, GTK_VALUE_UINT(*arg)); + redraw = TRUE; + break; + + case ARG_LENGTH_FUNCTION: + waveview->length_function = GTK_VALUE_POINTER(*arg); + redraw = TRUE; + break; + case ARG_SOURCEFILE_LENGTH_FUNCTION: + waveview->sourcefile_length_function = GTK_VALUE_POINTER(*arg); + redraw = TRUE; + break; + + case ARG_PEAK_FUNCTION: + waveview->peak_function = GTK_VALUE_POINTER(*arg); + redraw = TRUE; + break; + + case ARG_GAIN_FUNCTION: + waveview->gain_curve_function = GTK_VALUE_POINTER(*arg); + redraw = TRUE; + break; + + case ARG_GAIN_SRC: + waveview->gain_src = GTK_VALUE_POINTER(*arg); + if (waveview->cache_updater) { + waveview->cache->start = 0; + waveview->cache->end = 0; + } + redraw = TRUE; + calc_bounds = TRUE; + break; + + case ARG_CACHE: + waveview->cache = GTK_VALUE_POINTER(*arg); + redraw = TRUE; + break; + + + case ARG_CACHE_UPDATER: + waveview->cache_updater = GTK_VALUE_BOOL(*arg); + redraw = TRUE; + break; + + case ARG_SAMPLES_PER_PIXEL: + if ((waveview->samples_per_unit = GTK_VALUE_DOUBLE(*arg)) < 1.0) { + waveview->samples_per_unit = 1.0; + } + if (waveview->cache_updater) { + waveview->cache->start = 0; + waveview->cache->end = 0; + } + redraw = TRUE; + calc_bounds = TRUE; + break; + + case ARG_AMPLITUDE_ABOVE_AXIS: + waveview->amplitude_above_axis = GTK_VALUE_DOUBLE(*arg); + redraw = TRUE; + break; + + case ARG_X: + if (waveview->x != GTK_VALUE_DOUBLE (*arg)) { + waveview->x = GTK_VALUE_DOUBLE (*arg); + calc_bounds = TRUE; + } + break; + + case ARG_Y: + if (waveview->y != GTK_VALUE_DOUBLE (*arg)) { + waveview->y = GTK_VALUE_DOUBLE (*arg); + calc_bounds = TRUE; + } + break; + + case ARG_HEIGHT: + if (waveview->height != fabs (GTK_VALUE_DOUBLE (*arg))) { + waveview->height = fabs (GTK_VALUE_DOUBLE (*arg)); + redraw = TRUE; + } + break; + + case ARG_WAVE_COLOR: + if (waveview->wave_color != GTK_VALUE_INT(*arg)) { + waveview->wave_color = GTK_VALUE_INT(*arg); + redraw = TRUE; + } + break; + + case ARG_RECTIFIED: + if (waveview->rectified != GTK_VALUE_BOOL(*arg)) { + waveview->rectified = GTK_VALUE_BOOL(*arg); + redraw = TRUE; + } + break; + case ARG_REGION_START: + waveview->region_start = GTK_VALUE_UINT(*arg); + redraw = TRUE; + calc_bounds = TRUE; + break; + + + default: + break; + } + + if (calc_bounds) { + gtk_canvas_waveview_reset_bounds (item); + } + + if (redraw) { + gtk_canvas_item_request_update (item); + } + +} + +static void +gtk_canvas_waveview_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GtkCanvasWaveView *waveview; + + waveview = GTK_CANVAS_WAVEVIEW (object); + + switch (arg_id) { + case ARG_DATA_SRC: + GTK_VALUE_POINTER(*arg) = waveview->data_src; + break; + + case ARG_CHANNEL: + GTK_VALUE_UINT(*arg) = waveview->channel; + break; + + case ARG_LENGTH_FUNCTION: + GTK_VALUE_POINTER(*arg) = waveview->length_function; + break; + + case ARG_SOURCEFILE_LENGTH_FUNCTION: + GTK_VALUE_POINTER(*arg) = waveview->sourcefile_length_function; + break; + + case ARG_PEAK_FUNCTION: + GTK_VALUE_POINTER(*arg) = waveview->peak_function; + break; + + case ARG_GAIN_FUNCTION: + GTK_VALUE_POINTER(*arg) = waveview->gain_curve_function; + break; + + case ARG_GAIN_SRC: + GTK_VALUE_POINTER(*arg) = waveview->gain_src; + break; + + case ARG_CACHE: + GTK_VALUE_POINTER(*arg) = waveview->cache; + break; + + case ARG_CACHE_UPDATER: + GTK_VALUE_BOOL(*arg) = waveview->cache_updater; + break; + + case ARG_SAMPLES_PER_PIXEL: + GTK_VALUE_DOUBLE(*arg) = waveview->samples_per_unit; + break; + + case ARG_AMPLITUDE_ABOVE_AXIS: + GTK_VALUE_DOUBLE(*arg) = waveview->amplitude_above_axis; + break; + + case ARG_X: + GTK_VALUE_DOUBLE (*arg) = waveview->x; + break; + + case ARG_Y: + GTK_VALUE_DOUBLE (*arg) = waveview->y; + break; + + case ARG_HEIGHT: + GTK_VALUE_DOUBLE (*arg) = waveview->height; + break; + + case ARG_WAVE_COLOR: + GTK_VALUE_INT (*arg) = waveview->wave_color; + break; + + case ARG_RECTIFIED: + GTK_VALUE_BOOL (*arg) = waveview->rectified; + + case ARG_REGION_START: + GTK_VALUE_UINT (*arg) = waveview->region_start; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +gtk_canvas_waveview_update (GtkCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + GtkCanvasWaveView *waveview; + double x, y; + + waveview = GTK_CANVAS_WAVEVIEW (item); + +// check_cache (waveview, "start of update"); + + if (parent_class->update) + (* parent_class->update) (item, affine, clip_path, flags); + + gtk_canvas_waveview_reset_bounds (item); + + /* get the canvas coordinates of the view. Do NOT use affines + for this, because they do not round to the integer units used + by the canvas, resulting in subtle pixel-level errors later. + */ + + x = waveview->x; + y = waveview->y; + + gtk_canvas_item_i2w (item, &x, &y); + gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &waveview->bbox_ulx, &waveview->bbox_uly); + + waveview->samples = waveview->length_function (waveview->data_src); + + x = waveview->x + (waveview->samples / waveview->samples_per_unit); + y = waveview->y + waveview->height; + + gtk_canvas_item_i2w (item, &x, &y); + gtk_canvas_w2c (GTK_CANVAS(item->canvas), x, y, &waveview->bbox_lrx, &waveview->bbox_lry); + + /* cache the half-height and the end point in canvas units */ + + waveview->half_height = waveview->height / 2.0; + + /* parse the color */ + + UINT_TO_RGBA (waveview->wave_color, &waveview->wave_r, &waveview->wave_g, &waveview->wave_b, + &waveview->wave_a); + +// check_cache (waveview, "end of update"); +} + +static void +gtk_canvas_waveview_render (GtkCanvasItem *item, + GtkCanvasBuf *buf) +{ + GtkCanvasWaveView *waveview; + gulong s1, s2; + int clip_length = 0; + int pymin, pymax; + int cache_index; + double half_height; + int x, end, begin; + + waveview = GTK_CANVAS_WAVEVIEW (item); + +// check_cache (waveview, "start of render"); + + if (parent_class->render) { + (*parent_class->render) (item, buf); + } + + if (buf->is_bg) { + gtk_canvas_buf_ensure_buf (buf); + buf->is_bg = FALSE; + } + + begin = MAX(waveview->bbox_ulx,buf->rect.x0); + + if (waveview->bbox_lrx >= 0) { + end = MIN(waveview->bbox_lrx,buf->rect.x1); + } else { + end = buf->rect.x1; + } + + if (begin == end) { + return; + } + + s1 = floor ((begin - waveview->bbox_ulx) * waveview->samples_per_unit) ; + + // fprintf (stderr, "0x%x begins at sample %f\n", waveview, waveview->bbox_ulx * waveview->samples_per_unit); + + if (end == waveview->bbox_lrx) { + /* This avoids minor rounding errors when we have the + entire region visible. + */ + s2 = waveview->samples; + } else { + s2 = s1 + floor ((end - begin) * waveview->samples_per_unit); + } + +#if 0 + printf ("0x%x r (%d..%d)(%d..%d) bbox (%d..%d)(%d..%d)" + " b/e %d..%d s= %lu..%lu\n", + waveview, + buf->rect.x0, + buf->rect.x1, + buf->rect.y0, + buf->rect.y1, + waveview->bbox_ulx, + waveview->bbox_lrx, + waveview->bbox_uly, + waveview->bbox_lry, + begin, end, s1, s2); +#endif + + /* now ensure that the cache is full and properly + positioned. + */ + +// check_cache (waveview, "pre-ensure"); + + if (waveview->cache_updater && waveview->reload_cache_in_render) { + waveview->cache->start = 0; + waveview->cache->end = 0; + waveview->reload_cache_in_render = FALSE; + } + + cache_index = gtk_canvas_waveview_ensure_cache (waveview, s1, s2); + +// check_cache (waveview, "post-ensure"); + + /* + Now draw each line, clipping it appropriately. The clipping + is done by the macros PAINT_FOO(). + */ + + half_height = waveview->half_height; + +/* this makes it slightly easier to comprehend whats going on */ + +#define origin half_height + + for (x = begin; x < end; x++) { + + double max, min; + int clip_max, clip_min; + + clip_max = 0; + clip_min = 0; + + max = waveview->cache->data[cache_index].max; + min = waveview->cache->data[cache_index].min; + + if (max >= 1.0) { + max = 1.0; + clip_max = 1; + } + + if (min <= -1.0) { + min = -1.0; + clip_min = 1; + } + + /* don't rectify at single-sample zoom */ + + if (waveview->rectified && waveview->samples_per_unit > 1) { + + if (fabs (min) > fabs (max)) { + max = fabs (min); + } + + max = max * waveview->height; + + pymax = (int) rint ((item->y1 + waveview->height - max) * item->canvas->pixels_per_unit); + pymin = (int) rint ((item->y1 + waveview->height) * item->canvas->pixels_per_unit); + + } else { + + max = max * half_height; + min = min * half_height; + + pymax = (int) rint ((item->y1 + origin - max) * item->canvas->pixels_per_unit); + pymin = (int) rint ((item->y1 + origin - min) * item->canvas->pixels_per_unit); + } + + /* OK, now fill the RGB buffer at x=i with a line between pymin and pymax, + or, if samples_per_unit == 1, then a dot at each location. + */ + + if (pymax == pymin) { + PAINT_DOTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymin); + } else { + PAINT_VERTA(buf, waveview->wave_r, waveview->wave_g, waveview->wave_b, waveview->wave_a, x, pymax, pymin); + } + + /* show clipped waveforms with small red lines */ + + if (clip_max || clip_min) { + clip_length = MIN(5,(waveview->height/4)); + } + + if (clip_max) { + PAINT_VERT(buf, 255, 0, 0, x, pymax, pymax+clip_length); + } + + if (clip_min) { + PAINT_VERT(buf, 255, 0, 0, x, pymin-clip_length, pymin); + } + + /* presto, we're done */ + + cache_index++; + } + +#undef origin + +} + +static void +gtk_canvas_waveview_draw (GtkCanvasItem *item, + GdkDrawable *drawable, + int x, int y, + int width, int height) +{ + GtkCanvasWaveView *waveview; + + waveview = GTK_CANVAS_WAVEVIEW (item); + + if (parent_class->draw) { + (* parent_class->draw) (item, drawable, x, y, width, height); + } + + fprintf (stderr, "please don't use the CanvasWaveView item in a non-aa Canvas\n"); + abort (); +} + +static void +gtk_canvas_waveview_bounds (GtkCanvasItem *item, double *x1, double *y1, double *x2, double *y2) +{ + GtkCanvasWaveView *waveview = GTK_CANVAS_WAVEVIEW (item); + + *x1 = waveview->x; + *y1 = waveview->y; + + *x2 = ceil (*x1 + (waveview->length_function (waveview->data_src) / waveview->samples_per_unit)); + *y2 = *y1 + waveview->height; + +#if 0 + x = 0; y = 0; + gtk_canvas_item_i2w (item, &x, &y); + gtk_canvas_w2c_d (GTK_CANVAS(item->canvas), x, y, &a, &b); + x = *x2; + y = *y2; + gtk_canvas_item_i2w (item, &x, &y); + gtk_canvas_w2c_d (GTK_CANVAS(item->canvas), x, y, &c, &d); + printf ("item bounds now (%g,%g),(%g,%g)\n", a, b, c, d); +#endif + +} + +static double +gtk_canvas_waveview_point (GtkCanvasItem *item, double x, double y, int cx, int cy, GtkCanvasItem **actual_item) +{ + /* XXX for now, point is never inside the wave + GtkCanvasWaveView *waveview; + double x1, y1, x2, y2; + double dx, dy; + */ + + return DBL_MAX; + +#if 0 + waveview = GTK_CANVAS_WAVEVIEW (item); + + *actual_item = item; + + /* Find the bounds for the rectangle plus its outline width */ + + gtk_canvas_waveview_bounds (item, &x1, &y1, &x2, &y2); + + /* Is point inside rectangle */ + + if ((x >= x1) && (y >= y1) && (x <= x2) && (y <= y2)) { + return 0.0; + } + + /* Point is outside rectangle */ + + if (x < x1) + dx = x1 - x; + else if (x > x2) + dx = x - x2; + else + dx = 0.0; + + if (y < y1) + dy = y1 - y; + else if (y > y2) + dy = y - y2; + else + dy = 0.0; + + return sqrt (dx * dx + dy * dy); +#endif +} + diff --git a/gtk2_ardour/canvas-waveview.h b/gtk2_ardour/canvas-waveview.h new file mode 100644 index 0000000000..b868abfa61 --- /dev/null +++ b/gtk2_ardour/canvas-waveview.h @@ -0,0 +1,128 @@ +/* gtk-canvas-waveview.h: GtkCanvas item for displaying wave data + * + * Copyright (C) 2001 Paul Davis + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef __GTK_CANVAS_WAVEVIEW_H__ +#define __GTK_CANVAS_WAVEVIEW_H__ + +#include + +#include +#include "gtk-canvas/gtk-canvas.h" + +BEGIN_GTK_CANVAS_DECLS + +/* Wave viewer item for canvas. + */ + +#define GTK_CANVAS_TYPE_CANVAS_WAVEVIEW (gtk_canvas_waveview_get_type ()) +#define GTK_CANVAS_WAVEVIEW(obj) (GTK_CHECK_CAST ((obj), GTK_CANVAS_TYPE_CANVAS_WAVEVIEW, GtkCanvasWaveView)) +#define GTK_CANVAS_WAVEVIEW_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_CANVAS_TYPE_CANVAS_WAVEVIEW, GtkCanvasWaveViewClass)) +#define GTK_CANVAS_IS_CANVAS_WAVEVIEW(obj) (GTK_CHECK_TYPE ((obj), GTK_CANVAS_TYPE_CANVAS_WAVEVIEW)) +#define GTK_CANVAS_IS_CANVAS_WAVEVIEW_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_CANVAS_TYPE_CANVAS_WAVEVIEW)) + +typedef struct _GtkCanvasWaveView GtkCanvasWaveView; +typedef struct _GtkCanvasWaveViewClass GtkCanvasWaveViewClass; +typedef struct _GtkCanvasWaveViewChannelInfo GtkCanvasWaveViewChannelInfo; +typedef struct _GtkCanvasWaveViewCacheEntry GtkCanvasWaveViewCacheEntry; +typedef struct _GtkCanvasWaveViewCache GtkCanvasWaveViewCache; + +/* XXX this needs to be synced with ardour/source.h PeakData */ + +struct _GtkCanvasWaveViewCacheEntry +{ + float min; + float max; +}; + +struct _GtkCanvasWaveViewCache +{ + GtkCanvasWaveViewCacheEntry* data; + gint32 allocated; + gint32 data_size; + gulong start; + gulong end; +}; + +GtkCanvasWaveViewCache* gtk_canvas_waveview_cache_new (); +void gtk_canvas_waveview_cache_destroy (GtkCanvasWaveViewCache*); + +struct _GtkCanvasWaveView +{ + GtkCanvasItem item; + + GtkCanvasWaveViewCache *cache; + gboolean cache_updater; + gint screen_width; + + void *data_src; + guint32 channel; + void (*peak_function)(void*,gulong,gulong,gulong,gpointer,guint32,double); + gulong (*length_function)(void *); + gulong (*sourcefile_length_function)(void*); + void (*gain_curve_function)(void *arg, double start, double end, float* vector, guint32 veclen); + void *gain_src; + + /* x-axis: samples per canvas unit. */ + double samples_per_unit; + + /* y-axis: amplitude_above_axis. + * + * the default is that an (scaled, normalized -1.0 ... +1.0) amplitude of 1.0 + * corresponds to the top of the area assigned to the waveview. + * + * larger values will expand the vertical scale, cutting off the peaks/troughs. + * smaller values will decrease the vertical scale, moving peaks/troughs toward + * the middle of the area assigned to the waveview. + */ + + double amplitude_above_axis; + double x; + double y; + double height; + double half_height; + uint32_t wave_color; + + char rectified; + + /* These are updated by the update() routine + to optimize the render() routine, which may + be called several times after a single update(). + */ + + int32_t bbox_ulx; + int32_t bbox_uly; + int32_t bbox_lrx; + int32_t bbox_lry; + unsigned char wave_r, wave_g, wave_b, wave_a; + uint32_t samples; + uint32_t region_start; + int32_t reload_cache_in_render; +}; + +struct _GtkCanvasWaveViewClass { + GtkCanvasItemClass parent_class; +}; + +GtkType gtk_canvas_waveview_get_type (void); + +END_GTK_CANVAS_DECLS + +#endif /* __GTK_CANVAS_WAVEVIEW_H__ */ diff --git a/gtk2_ardour/check_mark.h b/gtk2_ardour/check_mark.h new file mode 100644 index 0000000000..78f7424028 --- /dev/null +++ b/gtk2_ardour/check_mark.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +static const gchar* check_xpm[] = { +"13 10 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" .. ", +" ++++++++.++.", +" + .++. ", +" +. .++.+ ", +" .+. .++. + ", +".+++..++. + ", +" .+++++. + ", +" +.+++. + ", +" ++.+.++++++ ", +" . "}; + +static const gchar* empty_xpm[] = { +"13 10 2 1", +" c None", +"+ c #FFFFFF", +" ", +" +++++++++++ ", +" + + ", +" + + ", +" + + ", +" + + ", +" + + ", +" + + ", +" +++++++++++ ", +" ",}; + diff --git a/gtk2_ardour/connection_editor.cc b/gtk2_ardour/connection_editor.cc new file mode 100644 index 0000000000..c2dbaaa1fd --- /dev/null +++ b/gtk2_ardour/connection_editor.cc @@ -0,0 +1,692 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ +#include + +#include +#include +#include + +#include "connection_editor.h" + +#include +#include +#include +#include + +#include "utils.h" +#include "keyboard.h" +#include "prompter.h" + +#include "i18n.h" + +#include + +using namespace std; +using namespace ARDOUR; +using namespace Gtk; +using namespace SigC; + +ConnectionEditor::ConnectionEditor () + : ArdourDialog ("connection editor"), + input_connection_display (1), + output_connection_display (1), + input_frame (_("Input Connections")), + output_frame (_("Output Connections")), + new_input_connection_button (_("New Input")), + new_output_connection_button (_("New Output")), + delete_connection_button (_("Delete")), + clear_button (_("Clear")), + add_port_button (_("Add Port")), + ok_button (_("Close")), + cancel_button (_("Cancel")), + rescan_button (_("Rescan")) + +{ + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK); + + session = 0; + selected_port = -1; + current_connection = 0; + push_at_front = false; + + set_name ("ConnectionEditorWindow"); + + ok_button.set_name ("ConnectionEditorButton"); + cancel_button.set_name ("ConnectionEditorButton"); + rescan_button.set_name ("ConnectionEditorButton"); + new_input_connection_button.set_name ("ConnectionEditorButton"); + new_output_connection_button.set_name ("ConnectionEditorButton"); + clear_button.set_name ("ConnectionEditorButton"); + + button_frame.set_name ("ConnectionEditorFrame"); + input_frame.set_name ("ConnectionEditorFrame"); + output_frame.set_name ("ConnectionEditorFrame"); + + button_box.set_spacing (15); + button_box.set_border_width (5); + Gtkmmext::set_usize_to_display_given_text (ok_button, _("OK"), 40, 15); + button_box.pack_end (ok_button, false, false); + // button_box.pack_end (cancel_button, false, false); + cancel_button.hide(); + button_frame.add (button_box); + + ok_button.clicked.connect (slot (*this, &ConnectionEditor::accept)); + cancel_button.clicked.connect (slot (*this, &ConnectionEditor::cancel)); + cancel_button.clicked.connect (slot (*this, &ConnectionEditor::rescan)); + + notebook.set_name ("ConnectionEditorNotebook"); + notebook.set_usize (-1, 125); + + clear_button.set_name ("ConnectionEditorButton"); + add_port_button.set_name ("ConnectionEditorButton"); + Gtkmmext::set_usize_to_display_given_text (add_port_button, _("Add Port"), 35, 15); + + selector_frame.set_name ("ConnectionEditorFrame"); + port_frame.set_name ("ConnectionEditorFrame"); + + selector_frame.set_label (_("Available Ports")); + + selector_button_box.set_spacing (5); + selector_button_box.set_border_width (5); + Gtkmmext::set_usize_to_display_given_text (rescan_button, _("Rescan"), 35, 15); + selector_button_box.pack_start (rescan_button, false, false); + + selector_box.set_spacing (5); + selector_box.set_border_width (5); + selector_box.pack_start (notebook); + selector_box.pack_start (selector_button_box); + + selector_frame.add (selector_box); + + port_box.set_spacing (5); + port_box.set_border_width (3); + + port_button_box.set_spacing (5); + port_button_box.set_border_width (2); + + port_button_box.pack_start (add_port_button, false, false); + port_and_button_box.set_border_width (5); + port_and_button_box.pack_start (port_button_box, false, false); + port_and_button_box.pack_start (port_box); + + port_frame.add (port_and_button_box); + + port_and_selector_box.set_spacing (5); + port_and_selector_box.pack_start (port_frame); + port_and_selector_box.pack_start (selector_frame); + + right_vbox.set_spacing (5); + right_vbox.set_border_width (5); + right_vbox.pack_start (port_and_selector_box); + + input_connection_display.set_shadow_type (GTK_SHADOW_IN); + input_connection_display.set_selection_mode (GTK_SELECTION_SINGLE); + input_connection_display.set_usize (80, -1); + input_connection_display.set_name ("ConnectionEditorConnectionList"); + input_connection_display.select_row.connect (bind (slot (*this, &ConnectionEditor::connection_selected), true)); + + output_connection_display.set_shadow_type (GTK_SHADOW_IN); + output_connection_display.set_selection_mode (GTK_SELECTION_SINGLE); + output_connection_display.set_usize (80, -1); + output_connection_display.set_name ("ConnectionEditorConnectionList"); + output_connection_display.select_row.connect (bind (slot (*this, &ConnectionEditor::connection_selected), false)); + + input_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + output_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + input_scroller.add_with_viewport (input_connection_display); + output_scroller.add_with_viewport (output_connection_display); + + input_box.set_border_width (5); + input_box.set_spacing (5); + input_box.pack_start (input_scroller); + input_box.pack_start (new_input_connection_button, false, false); + input_frame.add (input_box); + + output_box.set_border_width (5); + output_box.set_spacing (5); + output_box.pack_start (output_scroller); + output_box.pack_start (new_output_connection_button, false, false); + output_frame.add (output_box); + + connection_box.set_spacing (5); + connection_box.pack_start (input_frame); + connection_box.pack_start (output_frame); + + left_vbox.set_spacing (5); + left_vbox.pack_start (connection_box); + + main_hbox.set_border_width (10); + main_hbox.set_spacing (5); + main_hbox.pack_start (left_vbox); + main_hbox.pack_start (right_vbox); + + main_vbox.set_border_width (10); + main_vbox.set_spacing (5); + main_vbox.pack_start (main_hbox); + main_vbox.pack_start (button_frame, false, false); + + set_title (_("ardour: connections")); + add (main_vbox); + + delete_event.connect (bind (slot (just_hide_it), reinterpret_cast (this))); + + clear_button.clicked.connect (slot (*this, &ConnectionEditor::clear)); + add_port_button.clicked.connect (slot (*this, &ConnectionEditor::add_port)); + new_input_connection_button.clicked.connect (bind (slot (*this, &ConnectionEditor::new_connection), true)); + new_output_connection_button.clicked.connect (bind (slot (*this, &ConnectionEditor::new_connection), false)); + delete_connection_button.clicked.connect (slot (*this, &ConnectionEditor::delete_connection)); +} + +ConnectionEditor::~ConnectionEditor() +{ +} + +void +ConnectionEditor::set_session (Session *s) +{ + if (s != session) { + + ArdourDialog::set_session (s); + + if (session) { + session->ConnectionAdded.connect (slot (*this, &ConnectionEditor::proxy_add_connection_and_select)); + session->ConnectionRemoved.connect (slot (*this, &ConnectionEditor::proxy_remove_connection)); + } else { + hide (); + } + } +} + +void +ConnectionEditor::rescan () +{ + refill_connection_display (); + display_ports (); +} + +void +ConnectionEditor::cancel () +{ + hide (); +} + +void +ConnectionEditor::accept () +{ + hide (); +} + +void +ConnectionEditor::clear () +{ + if (current_connection) { + current_connection->clear (); + } +} + +gint +ConnectionEditor::map_event_impl (GdkEventAny *ev) +{ + refill_connection_display (); + return Window::map_event_impl (ev); +} + +void +ConnectionEditor::add_connection (ARDOUR::Connection *connection) +{ + using namespace CList_Helpers; + const char *rowtext[1]; + + rowtext[0] = connection->name().c_str(); + + if (dynamic_cast (connection)) { + if (push_at_front) { + input_connection_display.rows().push_front (rowtext); + input_connection_display.rows().front().set_data (connection); + } else { + input_connection_display.rows().push_back (rowtext); + input_connection_display.rows().back().set_data (connection); + } + } else { + if (push_at_front) { + output_connection_display.rows().push_front (rowtext); + output_connection_display.rows().front().set_data (connection); + } else { + output_connection_display.rows().push_back (rowtext); + output_connection_display.rows().back().set_data (connection); + } + } +} + +void +ConnectionEditor::remove_connection (ARDOUR::Connection *connection) +{ + using namespace Gtk::CList_Helpers; + RowList::iterator i; + RowList* rlist; + + if (dynamic_cast (connection)) { + rlist = &input_connection_display.rows(); + } else { + rlist = &output_connection_display.rows(); + } + + if ((i = rlist->find_data (connection)) != rlist->end()) { + rlist->erase (i); + } +} + +void +ConnectionEditor::proxy_add_connection_and_select (ARDOUR::Connection *connection) +{ + Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &ConnectionEditor::add_connection_and_select), connection)); +} + +void +ConnectionEditor::proxy_remove_connection (ARDOUR::Connection *connection) +{ + Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &ConnectionEditor::remove_connection), connection)); +} + +void +ConnectionEditor::add_connection_and_select (ARDOUR::Connection *connection) +{ + add_connection (connection); + + if (dynamic_cast (connection)) { + input_connection_display.rows().front().select (); + } else { + output_connection_display.rows().front().select (); + } +} + +void +ConnectionEditor::refill_connection_display () +{ + input_connection_display.clear(); + output_connection_display.clear(); + + current_connection = 0; + + if (session) { + session->foreach_connection (this, &ConnectionEditor::add_connection); + } +} + +void +ConnectionEditor::connection_selected (gint row, gint col, GdkEvent *ev, bool input) +{ + ARDOUR::Connection *old_current = current_connection; + + + if (input) { + output_connection_display.unselect_all (); + current_connection = reinterpret_cast (input_connection_display.row(row).get_data()); + } else { + input_connection_display.unselect_all (); + current_connection = reinterpret_cast (output_connection_display.row(row).get_data()); + } + + if (old_current != current_connection) { + config_connection.disconnect (); + connect_connection.disconnect (); + } + + if (current_connection) { + config_connection = current_connection->ConfigurationChanged.connect + (bind (slot (*this, &ConnectionEditor::configuration_changed), input)); + connect_connection = current_connection->ConnectionsChanged.connect + (bind (slot (*this, &ConnectionEditor::connections_changed), input)); + } + + display_connection_state (input); + display_ports (); +} + +void +ConnectionEditor::configuration_changed (bool for_input) +{ + display_connection_state (for_input); +} + +void +ConnectionEditor::connections_changed (int which_port, bool for_input) +{ + display_connection_state (for_input); +} + +void +ConnectionEditor::display_ports () +{ + if (session == 0 || current_connection == 0) { + return; + } + + using namespace Notebook_Helpers; + using namespace CList_Helpers; + + typedef map > > PortMap; + PortMap portmap; + const char **ports; + PageList& pages = notebook.pages(); + gint current_page; + vector rowdata; + bool for_input; + + current_page = notebook.get_current_page_num (); + pages.clear (); + + /* get relevant current JACK ports */ + + for_input = (dynamic_cast (current_connection) != 0); + + ports = session->engine().get_ports ("", JACK_DEFAULT_AUDIO_TYPE, for_input?JackPortIsOutput:JackPortIsInput); + + if (ports == 0) { + return; + } + + /* find all the client names and group their ports into a list-by-client */ + + for (int n = 0; ports[n]; ++n) { + + pair > > newpair; + pair strpair; + pair result; + + string str = ports[n]; + string::size_type pos; + string portname; + + pos = str.find (':'); + + newpair.first = str.substr (0, pos); + portname = str.substr (pos+1); + + result = portmap.insert (newpair); + + strpair.first = portname; + strpair.second = str; + + result.first->second.push_back (strpair); + } + + PortMap::iterator i; + + for (i = portmap.begin(); i != portmap.end(); ++i) { + + Box *client_box = manage (new VBox); + Gtk::CList *client_port_display = manage (new Gtk::CList (1)); + ScrolledWindow *scroller = manage (new ScrolledWindow); + + scroller->add_with_viewport (*client_port_display); + scroller->set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + client_box->pack_start (*scroller); + + client_port_display->set_selection_mode (GTK_SELECTION_BROWSE); + client_port_display->set_name ("ConnectionEditorList"); + + for (vector >::iterator s = i->second.begin(); s != i->second.end(); ++s) { + + rowdata.clear (); + rowdata.push_back (s->first); + client_port_display->rows().push_back (rowdata); + client_port_display->rows().back().set_data (g_strdup (s->second.c_str()), free); + } + + client_port_display->columns_autosize (); + client_port_display->select_row.connect (bind (slot (*this, &ConnectionEditor::port_selection_handler), client_port_display)); + + Label *tab_label = manage (new Label); + + tab_label->set_name ("ConnectionEditorNotebookTab"); + tab_label->set_text ((*i).first); + + pages.push_back (TabElem (*client_box, *tab_label)); + } + + notebook.set_page (current_page); + notebook.show.connect (bind (slot (notebook, &Notebook::set_page), current_page)); + selector_box.show_all (); +} + +void +ConnectionEditor::display_connection_state (bool for_input) +{ + LockMonitor lm (port_display_lock, __LINE__, __FILE__); + uint32_t limit; + + if (session == 0 || current_connection == 0) { + return; + } + + string frame_label = _("Connection \""); + frame_label += current_connection->name(); + frame_label += _("\""); + port_frame.set_label (frame_label); + + for (slist::iterator i = port_displays.begin(); i != port_displays.end(); ) { + + slist::iterator tmp; + + tmp = i; + tmp++; + + port_box.remove (**i); + delete *i; + port_displays.erase (i); + + i = tmp; + } + + limit = current_connection->nports(); + + for (uint32_t n = 0; n < limit; ++n) { + + CList *clist; + ScrolledWindow *scroller; + + const gchar *title[1]; + char buf[32]; + string really_short_name; + + if (for_input) { + snprintf(buf, sizeof(buf)-1, _("in %d"), n+1); + } else { + snprintf(buf, sizeof(buf)-1, _("out %d"), n+1); + } + + title[0] = buf; + clist = manage (new CList (1, title)); + scroller = new ScrolledWindow; + + scroller->add_with_viewport (*clist); + scroller->set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + port_displays.insert (port_displays.end(), scroller); + port_box.pack_start (*scroller); + + clist->set_data ("port", (gpointer) ((intptr_t) n)); + + clist->set_name ("ConnectionEditorPortList"); + clist->click_column.connect (bind (slot (*this, &ConnectionEditor::port_column_click), clist)); + clist->set_selection_mode (GTK_SELECTION_SINGLE); + clist->set_shadow_type (GTK_SHADOW_IN); + + scroller->set_usize (-1, 75); + + /* now fill the clist with the current connections */ + + const ARDOUR::Connection::PortList& connections = current_connection->port_connections (n); + + for (ARDOUR::Connection::PortList::const_iterator i = connections.begin(); i != connections.end(); ++i) { + const gchar *data[1]; + + data[0] = (*i).c_str(); + clist->rows().push_back (data); + } + + clist->columns_autosize (); + clist->button_release_event.connect (bind (slot (*this, &ConnectionEditor::port_button_event), clist)); + } + + port_box.show_all (); +} + +void +ConnectionEditor::port_selection_handler (gint row, gint col, GdkEvent *ev, Gtk::CList *clist) +{ + using namespace CList_Helpers; + + string other_port_name = (char *) clist->rows()[row].get_data(); + + if (current_connection && selected_port >= 0) { + current_connection->add_connection (selected_port, other_port_name); + } + +} + +void +ConnectionEditor::add_port () +{ + if (current_connection) { + current_connection->add_port (); + } +} + +void +ConnectionEditor::port_column_click (gint col, CList *clist) +{ + /* Gack. CList's don't respond visually to a change + in their state, so rename them to force a style + switch. + */ + + LockMonitor lm (port_display_lock, __LINE__, __FILE__); + + int which_port = reinterpret_cast (clist->get_data ("port")); + + if (which_port != selected_port) { + + selected_port = which_port; + display_ports (); + + clist->set_name ("ConnectionEditorPortListSelected"); + + for (slist::iterator i = port_displays.begin(); i != port_displays.end(); ++i) { + + Widget *child = (*i)->get_child(); + + if (static_cast (child) != clist) { + child->set_name ("ConnectionEditorPortList"); + child->queue_draw (); + } + } + + } else { + + selected_port = -1; + clist->set_name ("ConnectionEditorPortList"); + clist->queue_draw(); + } +} + +gint +ConnectionEditor::connection_click (GdkEventButton *ev, CList *clist) +{ + gint row, col; + + if (clist->get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) { + return FALSE; + } + + current_connection = reinterpret_cast (clist->row(row).get_data ()); + + return TRUE; +} + +void +ConnectionEditor::new_connection (bool for_input) +{ + if (session == 0) { + return; + } + + ArdourPrompter prompter (true); + prompter.set_prompt (_("Name for new connection:")); + prompter.done.connect (Gtk::Main::quit.slot()); + prompter.show_all(); + + Gtk::Main::run(); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string name; + prompter.get_result (name); + + push_at_front = true; + + if (name.length()) { + if (for_input) { + session->add_connection (new ARDOUR::InputConnection (name)); + } else { + session->add_connection (new ARDOUR::OutputConnection (name)); + } + } + push_at_front = false; + } +} + +void +ConnectionEditor::delete_connection () +{ + if (session && current_connection) { + session->remove_connection (current_connection); + current_connection = 0; + } +} + +gint +ConnectionEditor::port_button_event (GdkEventButton *ev, CList *clist) +{ + int row, col; + + if (current_connection == 0) { + return FALSE; + } + + if (clist->get_selection_info ((int) ev->x, (int) ev->y, &row, &col) == 0) { + return FALSE; + } + + if (!(Keyboard::is_delete_event (ev))) { + return FALSE; + } + + string port_name = clist->cell (row, col).get_text (); + int which_port = (intptr_t) clist->get_data ("port"); + + current_connection->remove_connection (which_port, port_name); + + return TRUE; +} + + diff --git a/gtk2_ardour/connection_editor.h b/gtk2_ardour/connection_editor.h new file mode 100644 index 0000000000..a09a4560d1 --- /dev/null +++ b/gtk2_ardour/connection_editor.h @@ -0,0 +1,147 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_connection_editor_h__ +#define __ardour_gtk_connection_editor_h__ + +#if __GNUC__ >= 3 +#include +using __gnu_cxx::slist; +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "ardour_dialog.h" + +#include + +namespace ARDOUR { + class Session; + class Connection; +} + +class ConnectionEditor : public ArdourDialog { + public: + ConnectionEditor (); + ~ConnectionEditor (); + + void set_session (ARDOUR::Session *); + + protected: + gint map_event_impl (GdkEventAny *); + + private: + ARDOUR::Connection *current_connection; + int selected_port; + bool push_at_front; + + Gtk::CList input_connection_display; + Gtk::CList output_connection_display; + Gtk::ScrolledWindow input_scroller; + Gtk::ScrolledWindow output_scroller; + + Gtk::Frame input_frame; + Gtk::Frame output_frame; + Gtk::VBox input_box; + Gtk::VBox output_box; + Gtk::VBox connection_box; + + Gtk::HBox main_hbox; + Gtk::VBox main_vbox; + + Gtk::VBox left_vbox; + Gtk::VBox right_vbox; + Gtk::VBox port_and_selector_box; + + + Gtk::Button new_input_connection_button; + Gtk::Button new_output_connection_button; + Gtk::Button delete_connection_button; + + /* client/port selection */ + + Gtk::Notebook notebook; + Gtk::Button clear_client_button; + Gtk::Frame selector_frame; + Gtk::VBox selector_box; + Gtk::HBox selector_button_box; + + /* connection displays */ + + Gtk::HBox port_box; + Gtk::HBox port_button_box; + Gtk::VBox port_and_button_box; + Gtk::Frame port_frame; + Gtk::Button clear_button; + Gtk::Button add_port_button; + + PBD::Lock port_display_lock; + slist port_displays; + + Gtk::Button ok_button; + Gtk::Button cancel_button; + Gtk::Button rescan_button; + + Gtk::Frame button_frame; + Gtk::HBox button_box; + + void new_connection (bool for_input); + void delete_connection (); + + void display_ports (); + void display_connection_state (bool for_input); + + void add_connection (ARDOUR::Connection *); + void add_connection_and_select (ARDOUR::Connection *); + void proxy_add_connection_and_select (ARDOUR::Connection *); + void proxy_remove_connection (ARDOUR::Connection *); + void remove_connection (ARDOUR::Connection *); + void refill_connection_display (); + + void rescan (); + void clear (); + void cancel (); + void accept (); + + void port_selection_handler (gint row, gint col, GdkEvent *ev, Gtk::CList *); + + void add_port (); + void remove_port (int which_port); + + void port_column_click (gint col, Gtk::CList *clist); + gint port_button_event (GdkEventButton *, Gtk::CList *clist); + gint connection_click (GdkEventButton *ev, Gtk::CList *clist); + void connection_selected (gint, gint, GdkEvent *, bool); + + SigC::Connection config_connection; + SigC::Connection connect_connection; + void configuration_changed (bool); + void connections_changed (int, bool); +}; + +#endif /* __ardour_gtk_connection_editor_h__ */ diff --git a/gtk2_ardour/crossfade_edit.cc b/gtk2_ardour/crossfade_edit.cc new file mode 100644 index 0000000000..7667de3134 --- /dev/null +++ b/gtk2_ardour/crossfade_edit.cc @@ -0,0 +1,1343 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ardour_ui.h" +#include "crossfade_edit.h" +#include "rgb_macros.h" +#include "canvas-simplerect.h" +#include "canvas-waveview.h" +#include "keyboard.h" +#include "utils.h" +#include "gui_thread.h" + +using namespace std; +using namespace ARDOUR; +using namespace Gtk; +using namespace SigC; +using namespace Editing; + +#include "i18n.h" + +const int32_t CrossfadeEditor::Point::size = 7; +const double CrossfadeEditor::canvas_border = 10; +CrossfadeEditor::Presets* CrossfadeEditor::fade_in_presets = 0; +CrossfadeEditor::Presets* CrossfadeEditor::fade_out_presets = 0; + +#include "crossfade_xpms.h" + +CrossfadeEditor::Half::Half () + : line (0), + normative_curve (0.0, 1.0, 1.0, true), + gain_curve (0.0, 2.0, 1.0, true) +{ +} + +CrossfadeEditor::CrossfadeEditor (Session& s, Crossfade& xf, double my, double mxy) + : ArdourDialog (_("crossfade editor")), + cancel_button (_("Cancel")), + ok_button (_("OK")), + xfade (xf), + session (s), + clear_button (_("Clear")), + revert_button (_("Reset")), + audition_both_button (_("Fade")), + audition_left_dry_button (_("Out (dry)")), + audition_left_button (_("Out")), + audition_right_dry_button (_("In (dry)")), + audition_right_button (_("In")), + + preroll_button (_("With Pre-roll")), + postroll_button (_("With Post-roll")), + + miny (my), + maxy (mxy), + + fade_in_table (3, 3), + fade_out_table (3, 3), + + select_in_button (_("Fade In")), + select_out_button (_("Fade Out")) +{ + set_wmclass ("ardour_automationedit", "Ardour"); + set_name ("CrossfadeEditWindow"); + set_title (_("ardour: x-fade edit")); + set_position (GTK_WIN_POS_MOUSE); + + add (vpacker); + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_POINTER_MOTION_MASK); + + select_out_button.set_group (select_in_button.group()); + select_out_button.set_mode (false); + select_in_button.set_mode (false); + + if (fade_in_presets == 0) { + build_presets (); + } + + point_grabbed = false; + toplevel = 0; + + _canvas = gtk_canvas_new_aa (); + + canvas = wrap (_canvas); + canvas->size_allocate.connect (slot (*this, &CrossfadeEditor::canvas_allocation)); + canvas->set_usize (425, 200); + + toplevel = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 10.0, + "y2", 10.0, + "fill", (gboolean) TRUE, + "fill_color_rgba", (guint32) color_map[cCrossfadeEditorBase], + "outline_pixels", 0, + NULL); + + gtk_signal_connect (GTK_OBJECT(toplevel), + "event", + (GtkSignalFunc) _canvas_event, + this); + + fade[Out].line = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)), + gtk_canvas_line_get_type (), + "width_pixels", (guint) 1, + "fill_color_rgba", color_map[cCrossfadeEditorLine], + NULL); + + fade[Out].shading = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)), + gtk_canvas_polygon_get_type(), + "fill_color_rgba", color_map[cCrossfadeEditorLineShading], + NULL); + + fade[In].line = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)), + gtk_canvas_line_get_type (), + "width_pixels", (guint) 1, + "fill_color_rgba", color_map[cCrossfadeEditorLine], + NULL); + + fade[In].shading = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)), + gtk_canvas_polygon_get_type(), + "fill_color_rgba", color_map[cCrossfadeEditorLineShading], + NULL); + + gtk_signal_connect (GTK_OBJECT(fade[In].shading), + "event", + (GtkSignalFunc) _canvas_event, + this); + + + gtk_signal_connect (GTK_OBJECT(fade[Out].shading), + "event", + (GtkSignalFunc) _canvas_event, + this); + + gtk_signal_connect (GTK_OBJECT(fade[In].line), + "event", + (GtkSignalFunc) _curve_event, + this); + + gtk_signal_connect (GTK_OBJECT(fade[Out].line), + "event", + (GtkSignalFunc) _curve_event, + this); + + + select_in_button.set_name (X_("CrossfadeEditCurveButton")); + select_out_button.set_name (X_("CrossfadeEditCurveButton")); + + select_in_button.clicked.connect (bind (slot (this, &CrossfadeEditor::curve_select_clicked), In)); + select_out_button.clicked.connect (bind (slot (this, &CrossfadeEditor::curve_select_clicked), Out)); + + HBox* acbox = manage (new HBox); + + audition_box.set_border_width (7); + audition_box.set_spacing (5); + audition_box.set_homogeneous (false); + audition_box.pack_start (audition_left_dry_button, false, false); + audition_box.pack_start (audition_left_button, false, false); + audition_box.pack_start (audition_both_button, false, false); + audition_box.pack_start (audition_right_button, false, false); + audition_box.pack_start (audition_right_dry_button, false, false); + + Frame* audition_frame = manage (new Frame (_("Audition"))); + + audition_frame->set_name (X_("CrossfadeEditFrame")); + audition_frame->add (audition_box); + + acbox->pack_start (*audition_frame, true, false); + + Frame* canvas_frame = manage (new Frame); + canvas_frame->add (*canvas); + canvas_frame->set_shadow_type (GTK_SHADOW_IN); + + fade_in_table.attach (select_in_button, 0, 2, 0, 1, GTK_FILL|GTK_EXPAND); + fade_out_table.attach (select_out_button, 0, 2, 0, 1, GTK_FILL|GTK_EXPAND); + + Pixmap *pxmap; + Button* pbutton; + int row; + int col; + + row = 1; + col = 0; + + for (list::iterator i = fade_in_presets->begin(); i != fade_in_presets->end(); ++i) { + + pxmap = manage (new Pixmap ((*i)->xpm)); + pbutton = manage (new Button); + pbutton->add (*pxmap); + pbutton->set_name ("CrossfadeEditButton"); + pbutton->clicked.connect (bind (slot (*this, &CrossfadeEditor::apply_preset), *i)); + fade_in_table.attach (*pbutton, col, col+1, row, row+1); + fade_in_buttons.push_back (pbutton); + + col++; + + if (col == 2) { + col = 0; + row++; + } + } + + row = 1; + col = 0; + + for (list::iterator i = fade_out_presets->begin(); i != fade_out_presets->end(); ++i) { + + pxmap = manage (new Pixmap ((*i)->xpm)); + pbutton = manage (new Button); + pbutton->add (*pxmap); + pbutton->set_name ("CrossfadeEditButton"); + pbutton->clicked.connect (bind (slot (*this, &CrossfadeEditor::apply_preset), *i)); + fade_out_table.attach (*pbutton, col, col+1, row, row+1); + fade_out_buttons.push_back (pbutton); + + col++; + + if (col == 2) { + col = 0; + row++; + } + } + + clear_button.set_name ("CrossfadeEditButton"); + revert_button.set_name ("CrossfadeEditButton"); + ok_button.set_name ("CrossfadeEditButton"); + cancel_button.set_name ("CrossfadeEditButton"); + preroll_button.set_name ("CrossfadeEditButton"); + postroll_button.set_name ("CrossfadeEditButton"); + audition_both_button.set_name ("CrossfadeEditAuditionButton"); + audition_left_dry_button.set_name ("CrossfadeEditAuditionButton"); + audition_left_button.set_name ("CrossfadeEditAuditionButton"); + audition_right_dry_button.set_name ("CrossfadeEditAuditionButton"); + audition_right_button.set_name ("CrossfadeEditAuditionButton"); + + clear_button.clicked.connect (slot (*this, &CrossfadeEditor::clear)); + revert_button.clicked.connect (slot (*this, &CrossfadeEditor::reset)); + audition_both_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_toggled)); + audition_right_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_right_toggled)); + audition_right_dry_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_right_dry_toggled)); + audition_left_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_left_toggled)); + audition_left_dry_button.toggled.connect (slot (*this, &CrossfadeEditor::audition_left_dry_toggled)); + + action_box.set_border_width (7); + action_box.set_spacing (5); + action_box.set_homogeneous (false); + action_box.pack_end (cancel_button, false, false); + action_box.pack_end (ok_button, false, false); + action_box.pack_end (revert_button, false, false); + action_box.pack_end (clear_button, false, false); + + Frame* edit_frame = manage (new Frame (_("Edit"))); + edit_frame->set_name (X_("CrossfadeEditFrame")); + edit_frame->add (action_box); + + Gtk::HBox* action_center_box = manage (new HBox); + action_center_box->pack_start (*edit_frame, true, false); + + roll_box.pack_start (preroll_button, false, false); + roll_box.pack_start (postroll_button, false, false); + + Gtk::HBox* rcenter_box = manage (new HBox); + rcenter_box->pack_start (roll_box, true, false); + + VBox* vpacker2 = manage (new (VBox)); + + vpacker2->set_border_width (12); + vpacker2->set_spacing (7); + vpacker2->pack_start (*acbox, false, false); + vpacker2->pack_start (*rcenter_box, false, false); + vpacker2->pack_start (*action_center_box, false, false); + + curve_button_box.set_spacing (7); + curve_button_box.pack_start (fade_out_table, false, false, 12); + curve_button_box.pack_start (*vpacker2, false, false, 12); + curve_button_box.pack_start (fade_in_table, false, false, 12); + + vpacker.set_border_width (12); + vpacker.set_spacing (5); + vpacker.pack_start (*canvas_frame, true, true); + vpacker.pack_start (curve_button_box, false, false); + + /* button to allow hackers to check the actual curve values */ + +// Button* foobut = manage (new Button ("dump")); +// foobut->clicked.connect (slot (*this, &CrossfadeEditor::dump)); +// vpacker.pack_start (*foobut, false, false); + + current = In; + set (xfade.fade_in(), In); + + current = Out; + set (xfade.fade_out(), Out); + + curve_select_clicked (In); + + xfade.StateChanged.connect (slot (*this, &CrossfadeEditor::xfade_changed)); + + session.AuditionActive.connect (slot (*this, &CrossfadeEditor::audition_state_changed)); +} + +CrossfadeEditor::~CrossfadeEditor() +{ + /* most objects will be destroyed when the toplevel window is. */ + + for (list::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) { + delete *i; + } + + for (list::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) { + delete *i; + } +} + +void +CrossfadeEditor::dump () +{ + for (AutomationList::iterator i = fade[Out].normative_curve.begin(); i != fade[Out].normative_curve.end(); ++i) { + cerr << (*i)->when << ' ' << (*i)->value << endl; + } +} + +void +CrossfadeEditor::audition_state_changed (bool yn) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &CrossfadeEditor::audition_state_changed), yn)); + + if (!yn) { + audition_both_button.set_active (false); + audition_left_button.set_active (false); + audition_right_button.set_active (false); + audition_left_dry_button.set_active (false); + audition_right_dry_button.set_active (false); + } +} + +void +CrossfadeEditor::set (const ARDOUR::Curve& curve, WhichFade which) +{ + double firstx, endx; + ARDOUR::Curve::const_iterator the_end; + + for (list::iterator i = fade[which].points.begin(); i != fade[which].points.end(); ++i) { + delete *i; + } + + fade[which].points.clear (); + fade[which].gain_curve.clear (); + fade[which].normative_curve.clear (); + + if (curve.empty()) { + goto out; + } + + the_end = curve.const_end(); + --the_end; + + firstx = (*curve.const_begin())->when; + endx = (*the_end)->when; + + for (ARDOUR::Curve::const_iterator i = curve.const_begin(); i != curve.const_end(); ++i) { + + double xfract = ((*i)->when - firstx) / (endx - firstx); + double yfract = ((*i)->value - miny) / (maxy - miny); + + Point* p = make_point (); + + p->move_to (x_coordinate (xfract), y_coordinate (yfract), + xfract, yfract); + + fade[which].points.push_back (p); + } + + /* no need to sort because curve is already time-ordered */ + + out: + + swap (which, current); + redraw (); + swap (which, current); +} + +gint +CrossfadeEditor::_canvas_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) +{ + CrossfadeEditor* ed = static_cast (data); + return ed->canvas_event (item, event); +} + +gint +CrossfadeEditor::canvas_event (GtkCanvasItem* item, GdkEvent* event) +{ + switch (event->type) { + case GDK_BUTTON_PRESS: + add_control_point ((event->button.x - canvas_border)/effective_width(), + 1.0 - ((event->button.y - canvas_border)/effective_height())); + return TRUE; + break; + default: + break; + } + return FALSE; +} + +CrossfadeEditor::Point::~Point() +{ + gtk_object_destroy (GTK_OBJECT(box)); +} + +CrossfadeEditor::Point* +CrossfadeEditor::make_point () +{ + Point* p = new Point; + + p->box = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)), + gtk_canvas_simplerect_get_type(), + "fill", (gboolean) TRUE, + "fill_color_rgba", color_map[cCrossfadeEditorPointFill], + "outline_color_rgba", color_map[cCrossfadeEditorPointOutline], + "outline_pixels", (gint) 1, + NULL); + + p->curve = fade[current].line; + + gtk_object_set_data (GTK_OBJECT(p->box), "point", p); + gtk_signal_connect (GTK_OBJECT(p->box), "event", + (GtkSignalFunc) _point_event, + this); + + return p; +} + +void +CrossfadeEditor::add_control_point (double x, double y) +{ + PointSorter cmp; + + /* enforce end point x location */ + + if (fade[current].points.empty()) { + x = 0.0; + } else if (fade[current].points.size() == 1) { + x = 1.0; + } + + Point* p = make_point (); + + p->move_to (x_coordinate (x), y_coordinate (y), x, y); + + fade[current].points.push_back (p); + fade[current].points.sort (cmp); + + redraw (); +} + +void +CrossfadeEditor::Point::move_to (double nx, double ny, double xfract, double yfract) +{ + const double half_size = rint(size/2.0); + double x1 = nx - half_size; + double x2 = nx + half_size; + + gtk_canvas_item_set (box, + "x1", x1, + "x2", x2, + "y1", ny - half_size, + "y2", ny + half_size, + NULL); + x = xfract; + y = yfract; +} + +void +CrossfadeEditor::canvas_allocation (GtkAllocation *alloc) +{ + if (toplevel) { + gtk_canvas_item_set (toplevel, + "x1", 0.0, + "y1", 0.0, + "x2", (double) _canvas->allocation.width + canvas_border, + "y2", (double) _canvas->allocation.height + canvas_border, + NULL); + } + + gtk_canvas_set_scroll_region (GTK_CANVAS(_canvas), 0.0, 0.0, + _canvas->allocation.width, + _canvas->allocation.height); + + Point* end = make_point (); + PointSorter cmp; + + if (fade[In].points.size() > 1) { + Point* old_end = fade[In].points.back(); + fade[In].points.pop_back (); + end->move_to (x_coordinate (old_end->x), + y_coordinate (old_end->y), + old_end->x, old_end->y); + delete old_end; + } else { + double x = 1.0; + double y = 0.5; + end->move_to (x_coordinate (x), y_coordinate (y), x, y); + + } + + fade[In].points.push_back (end); + fade[In].points.sort (cmp); + + for (list::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) { + (*i)->move_to (x_coordinate((*i)->x), y_coordinate((*i)->y), + (*i)->x, (*i)->y); + } + + end = make_point (); + + if (fade[Out].points.size() > 1) { + Point* old_end = fade[Out].points.back(); + fade[Out].points.pop_back (); + end->move_to (x_coordinate (old_end->x), + y_coordinate (old_end->y), + old_end->x, old_end->y); + delete old_end; + } else { + double x = 1.0; + double y = 0.5; + end->move_to (x_coordinate (x), y_coordinate (y), x, y); + + } + + fade[Out].points.push_back (end); + fade[Out].points.sort (cmp); + + for (list::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) { + (*i)->move_to (x_coordinate ((*i)->x), + y_coordinate ((*i)->y), + (*i)->x, (*i)->y); + } + + WhichFade old_current = current; + current = In; + redraw (); + current = Out; + redraw (); + current = old_current; + + double spu = xfade.length() / (double) effective_width(); + + if (fade[In].waves.empty()) { + make_waves (xfade.in(), In); + } + + if (fade[Out].waves.empty()) { + make_waves (xfade.out(), Out); + } + + double ht; + vector::iterator i; + uint32_t n; + + ht = _canvas->allocation.height / xfade.in().n_channels(); + + for (n = 0, i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i, ++n) { + double yoff; + + yoff = n * ht; + + gtk_canvas_item_set ((*i), + "y", yoff, + "height", ht, + "samples_per_unit", spu, + NULL); + } + + ht = _canvas->allocation.height / xfade.out().n_channels(); + + for (n = 0, i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i, ++n) { + double yoff; + + yoff = n * ht; + + gtk_canvas_item_set ((*i), + "y", yoff, + "height", ht, + "samples_per_unit", spu, + NULL); + } + +} + +gint +CrossfadeEditor::_point_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) +{ + CrossfadeEditor* ed = static_cast (data); + return ed->point_event (item, event); +} + +gint +CrossfadeEditor::point_event (GtkCanvasItem* item, GdkEvent* event) +{ + Point* point = static_cast (gtk_object_get_data (GTK_OBJECT (item), "point")); + + if (point->curve != fade[current].line) { + return FALSE; + } + + switch (event->type) { + case GDK_BUTTON_PRESS: + point_grabbed = true; + break; + case GDK_BUTTON_RELEASE: + point_grabbed = false; + + if (Keyboard::is_delete_event (&event->button)) { + fade[current].points.remove (point); + delete point; + } + + redraw (); + break; + + case GDK_MOTION_NOTIFY: + if (point_grabbed) { + double new_x, new_y; + + /* can't drag first or last points horizontally */ + + if (point == fade[current].points.front() || point == fade[current].points.back()) { + new_x = point->x; + } else { + new_x = (event->motion.x - canvas_border)/effective_width(); + } + + new_y = 1.0 - ((event->motion.y - canvas_border)/effective_height()); + point->move_to (x_coordinate (new_x), y_coordinate (new_y), + new_x, new_y); + redraw (); + } + break; + default: + break; + } + return TRUE; +} + +gint +CrossfadeEditor::_curve_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) +{ + CrossfadeEditor* ed = static_cast (data); + return ed->curve_event (item, event); +} + +gint +CrossfadeEditor::curve_event (GtkCanvasItem* item, GdkEvent* event) +{ + /* treat it like a toplevel event */ + + return canvas_event (item, event); +} + +void +CrossfadeEditor::xfade_changed (Change ignored) +{ + set (xfade.fade_in(), In); + set (xfade.fade_out(), Out); +} + +void +CrossfadeEditor::redraw () +{ + if (_canvas->allocation.width < 2) { + return; + } + + jack_nframes_t len = xfade.length (); + + fade[current].normative_curve.clear (); + fade[current].gain_curve.clear (); + + for (list::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) { + fade[current].normative_curve.add ((*i)->x, (*i)->y); + fade[current].gain_curve.add (((*i)->x * len), (*i)->y); + } + + size_t npoints = (size_t) effective_width(); + float vec[npoints]; + + fade[current].normative_curve.get_vector (0, 1.0, vec, npoints); + + GtkCanvasPoints* pts = get_canvas_points ("xfade edit1", npoints); + GtkCanvasPoints* spts = get_canvas_points ("xfade edit2", npoints + 3); + + /* the shade coordinates *MUST* be in anti-clockwise order. + */ + + if (current == In) { + + /* lower left */ + + spts->coords[0] = canvas_border; + spts->coords[1] = effective_height() + canvas_border; + + /* lower right */ + + spts->coords[2] = effective_width() + canvas_border; + spts->coords[3] = effective_height() + canvas_border; + + /* upper right */ + + spts->coords[4] = effective_width() + canvas_border; + spts->coords[5] = canvas_border; + + + } else { + + /* upper left */ + + spts->coords[0] = canvas_border; + spts->coords[1] = canvas_border; + + /* lower left */ + + spts->coords[2] = canvas_border; + spts->coords[3] = effective_height() + canvas_border; + + /* lower right */ + + spts->coords[4] = effective_width() + canvas_border; + spts->coords[5] = effective_height() + canvas_border; + + } + + size_t last_spt = ((npoints + 3) * 2) - 2; + + for (size_t i = 0; i < npoints; ++i) { + + double y = vec[i]; + + pts->coords[i*2] = canvas_border + i; + pts->coords[(i*2)+1] = y_coordinate (y); + + spts->coords[last_spt - (i*2)] = canvas_border + i; + spts->coords[last_spt - (i*2) + 1] = pts->coords[(i*2)+1]; + } + + gtk_canvas_item_set (fade[current].line, "points", pts, NULL); + gtk_canvas_item_set (fade[current].shading, "points", spts, NULL); + + gtk_canvas_points_unref (pts); + gtk_canvas_points_unref (spts); + + for (vector::iterator i = fade[current].waves.begin(); i != fade[current].waves.end(); ++i) { + gtk_canvas_item_set ((*i), "gain_src", &fade[current].gain_curve, NULL); + } +} + +void +CrossfadeEditor::apply_preset (Preset *preset) +{ + for (list::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) { + delete *i; + } + + fade[current].points.clear (); + + for (Preset::iterator i = preset->begin(); i != preset->end(); ++i) { + Point* p = make_point (); + p->move_to (x_coordinate ((*i).x), y_coordinate ((*i).y), + (*i).x, (*i).y); + fade[current].points.push_back (p); + } + + redraw (); +} + +void +CrossfadeEditor::apply () +{ + _apply_to (&xfade); +} + +void +CrossfadeEditor::_apply_to (Crossfade* xf) +{ + ARDOUR::Curve& in (xf->fade_in()); + ARDOUR::Curve& out (xf->fade_out()); + + /* IN */ + + + ARDOUR::Curve::const_iterator the_end = in.const_end(); + --the_end; + + double firstx = (*in.begin())->when; + double endx = (*the_end)->when; + double miny = in.get_min_y (); + double maxy = in.get_max_y (); + + in.freeze (); + in.clear (); + + for (list::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) { + + double when = firstx + ((*i)->x * (endx - firstx)); + double value = (*i)->y; // miny + ((*i)->y * (maxy - miny)); + in.add (when, value); + } + + /* OUT */ + + the_end = out.const_end(); + --the_end; + + firstx = (*out.begin())->when; + endx = (*the_end)->when; + miny = out.get_min_y (); + maxy = out.get_max_y (); + + out.freeze (); + out.clear (); + + for (list::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) { + + double when = firstx + ((*i)->x * (endx - firstx)); + double value = (*i)->y; // miny + ((*i)->y * (maxy - miny)); + out.add (when, value); + } + + in.thaw (); + out.thaw (); +} + +void +CrossfadeEditor::setup (Crossfade* xfade) +{ + _apply_to (xfade); + xfade->set_active (true); + xfade->fade_in().solve (); + xfade->fade_out().solve (); +} + +void +CrossfadeEditor::clear () +{ + for (list::iterator i = fade[current].points.begin(); i != fade[current].points.end(); ++i) { + delete *i; + } + + fade[current].points.clear (); + + redraw (); +} + +void +CrossfadeEditor::reset () +{ + set (xfade.fade_in(), In); + set (xfade.fade_out(), Out); +} + +void +CrossfadeEditor::build_presets () +{ + Preset* p; + + fade_in_presets = new Presets; + fade_out_presets = new Presets; + + /* FADE OUT */ + + p = new Preset (hiin_xpm); + p->push_back (PresetPoint (0, 0)); + p->push_back (PresetPoint (0.0207373, 0.197222)); + p->push_back (PresetPoint (0.0645161, 0.525)); + p->push_back (PresetPoint (0.152074, 0.802778)); + p->push_back (PresetPoint (0.276498, 0.919444)); + p->push_back (PresetPoint (0.481567, 0.980556)); + p->push_back (PresetPoint (0.767281, 1)); + p->push_back (PresetPoint (1, 1)); + fade_in_presets->push_back (p); + + p = new Preset (loin_xpm); + p->push_back (PresetPoint (0, 0)); + p->push_back (PresetPoint (0.389401, 0.0333333)); + p->push_back (PresetPoint (0.629032, 0.0861111)); + p->push_back (PresetPoint (0.829493, 0.233333)); + p->push_back (PresetPoint (0.9447, 0.483333)); + p->push_back (PresetPoint (0.976959, 0.697222)); + p->push_back (PresetPoint (1, 1)); + fade_in_presets->push_back (p); + + p = new Preset (regin_xpm); + p->push_back (PresetPoint (0, 0)); + p->push_back (PresetPoint (0.0737327, 0.308333)); + p->push_back (PresetPoint (0.246544, 0.658333)); + p->push_back (PresetPoint (0.470046, 0.886111)); + p->push_back (PresetPoint (0.652074, 0.972222)); + p->push_back (PresetPoint (0.771889, 0.988889)); + p->push_back (PresetPoint (1, 1)); + fade_in_presets->push_back (p); + + p = new Preset (regin2_xpm); + p->push_back (PresetPoint (0, 0)); + p->push_back (PresetPoint (0.304147, 0.0694444)); + p->push_back (PresetPoint (0.529954, 0.152778)); + p->push_back (PresetPoint (0.725806, 0.333333)); + p->push_back (PresetPoint (0.847926, 0.558333)); + p->push_back (PresetPoint (0.919355, 0.730556)); + p->push_back (PresetPoint (1, 1)); + fade_in_presets->push_back (p); + + p = new Preset (linin_xpm); + p->push_back (PresetPoint (0, 0)); + p->push_back (PresetPoint (1, 1)); + fade_in_presets->push_back (p); + + /* FADE OUT */ + + p = new Preset (hiout_xpm); + p->push_back (PresetPoint (0, 1)); + p->push_back (PresetPoint (0.305556, 1)); + p->push_back (PresetPoint (0.548611, 0.991736)); + p->push_back (PresetPoint (0.759259, 0.931129)); + p->push_back (PresetPoint (0.918981, 0.68595)); + p->push_back (PresetPoint (0.976852, 0.22865)); + p->push_back (PresetPoint (1, 0)); + fade_out_presets->push_back (p); + + p = new Preset (regout_xpm); + p->push_back (PresetPoint (0, 1)); + p->push_back (PresetPoint (0.228111, 0.988889)); + p->push_back (PresetPoint (0.347926, 0.972222)); + p->push_back (PresetPoint (0.529954, 0.886111)); + p->push_back (PresetPoint (0.753456, 0.658333)); + p->push_back (PresetPoint (0.9262673, 0.308333)); + p->push_back (PresetPoint (1, 0)); + fade_out_presets->push_back (p); + + p = new Preset (loout_xpm); + p->push_back (PresetPoint (0, 1)); + p->push_back (PresetPoint (0.023041, 0.697222)); + p->push_back (PresetPoint (0.0553, 0.483333)); + p->push_back (PresetPoint (0.170507, 0.233333)); + p->push_back (PresetPoint (0.370968, 0.0861111)); + p->push_back (PresetPoint (0.610599, 0.0333333)); + p->push_back (PresetPoint (1, 0)); + fade_out_presets->push_back (p); + + p = new Preset (regout2_xpm); + p->push_back (PresetPoint (0, 1)); + p->push_back (PresetPoint (0.080645, 0.730556)); + p->push_back (PresetPoint (0.277778, 0.289256)); + p->push_back (PresetPoint (0.470046, 0.152778)); + p->push_back (PresetPoint (0.695853, 0.0694444)); + p->push_back (PresetPoint (1, 0)); + fade_out_presets->push_back (p); + + p = new Preset (linout_xpm); + p->push_back (PresetPoint (0, 1)); + p->push_back (PresetPoint (1, 0)); + fade_out_presets->push_back (p); +} + +void +CrossfadeEditor::curve_select_clicked (WhichFade wf) +{ + current = wf; + + if (wf == In) { + + for (vector::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) { + gtk_canvas_item_set ((*i), "wave_color", color_map[cSelectedCrossfadeEditorWave], NULL); + } + + for (vector::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) { + gtk_canvas_item_set ((*i), "wave_color", color_map[cCrossfadeEditorWave], NULL); + } + + gtk_canvas_item_set (fade[In].line, "fill_color_rgba", color_map[cSelectedCrossfadeEditorLine], NULL); + gtk_canvas_item_set (fade[Out].line, "fill_color_rgba", color_map[cCrossfadeEditorLine], NULL); + gtk_canvas_item_hide (fade[Out].shading); + gtk_canvas_item_show (fade[In].shading); + + for (list::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) { + gtk_canvas_item_hide ((*i)->box); + } + + for (list::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) { + gtk_canvas_item_show ((*i)->box); + } + + for (vector::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) { + (*i)->set_sensitive (false); + } + + for (vector::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) { + (*i)->set_sensitive (true); + } + + } else { + + for (vector::iterator i = fade[In].waves.begin(); i != fade[In].waves.end(); ++i) { + gtk_canvas_item_set ((*i), "wave_color", color_map[cCrossfadeEditorWave], NULL); + } + + for (vector::iterator i = fade[Out].waves.begin(); i != fade[Out].waves.end(); ++i) { + gtk_canvas_item_set ((*i), "wave_color", color_map[cSelectedCrossfadeEditorWave], NULL); + } + + gtk_canvas_item_set (fade[Out].line, "fill_color_rgba", color_map[cSelectedCrossfadeEditorLine], NULL); + gtk_canvas_item_set (fade[In].line, "fill_color_rgba", color_map[cCrossfadeEditorLine], NULL); + gtk_canvas_item_hide (fade[In].shading); + gtk_canvas_item_show (fade[Out].shading); + + for (list::iterator i = fade[In].points.begin(); i != fade[In].points.end(); ++i) { + gtk_canvas_item_hide ((*i)->box); + } + + for (list::iterator i = fade[Out].points.begin(); i != fade[Out].points.end(); ++i) { + gtk_canvas_item_show ((*i)->box); + } + + for (vector::iterator i = fade_out_buttons.begin(); i != fade_out_buttons.end(); ++i) { + (*i)->set_sensitive (true); + } + + for (vector::iterator i = fade_in_buttons.begin(); i != fade_in_buttons.end(); ++i) { + (*i)->set_sensitive (false); + } + + } +} + +double +CrossfadeEditor::x_coordinate (double& xfract) const +{ + xfract = min (1.0, xfract); + xfract = max (0.0, xfract); + + return canvas_border + (xfract * effective_width()); +} + +double +CrossfadeEditor::y_coordinate (double& yfract) const +{ + yfract = min (1.0, yfract); + yfract = max (0.0, yfract); + + return (_canvas->allocation.height - (canvas_border)) - (yfract * effective_height()); +} + +void +CrossfadeEditor::make_waves (AudioRegion& region, WhichFade which) +{ + gdouble ht; + uint32_t nchans = region.n_channels(); + guint32 color; + double spu; + + if (which == In) { + color = color_map[cSelectedCrossfadeEditorWave]; + } else { + color = color_map[cCrossfadeEditorWave]; + } + + ht = _canvas->allocation.height / (double) nchans; + spu = xfade.length() / (double) effective_width(); + + for (uint32_t n = 0; n < nchans; ++n) { + + gdouble yoff = n * ht; + + if (region.source(n).peaks_ready (bind (slot (*this, &CrossfadeEditor::peaks_ready), ®ion, which))) { + + GtkCanvasItem *wave = gtk_canvas_item_new (gtk_canvas_root (GTK_CANVAS(_canvas)), + gtk_canvas_waveview_get_type (), + "data_src", (gpointer) ®ion, + "cache_updater", (gboolean) TRUE, + "cache", gtk_canvas_waveview_cache_new (), + "channel", (guint32) n, + "length_function", (gpointer) region_length_from_c, + "sourcefile_length_function", (gpointer) sourcefile_length_from_c, + "peak_function", (gpointer) region_read_peaks_from_c, + "gain_function", (gpointer) curve_get_vector_from_c, + "gain_src", &fade[which].gain_curve, + "x", (double) canvas_border, + "y", yoff, + "height", ht, + "samples_per_unit", spu, + "amplitude_above_axis", 2.0, + "wave_color", color, + NULL); + + gtk_canvas_item_lower_to_bottom (wave); + fade[which].waves.push_back (wave); + } + } + + gtk_canvas_item_lower_to_bottom (toplevel); +} + +void +CrossfadeEditor::peaks_ready (AudioRegion* r, WhichFade which) +{ + /* this should never be called, because the peak files for an xfade + will be ready by the time we want them. but our API forces us + to provide this, so .. + */ + + make_waves (*r, which); +} + +void +CrossfadeEditor::audition_both () +{ + AudioPlaylist& pl (session.the_auditioner().prepare_playlist()); + jack_nframes_t preroll; + jack_nframes_t postroll; + jack_nframes_t length; + jack_nframes_t left_start_offset; + jack_nframes_t right_length; + jack_nframes_t left_length; + + if (preroll_button.get_active()) { + preroll = ARDOUR_UI::instance()->preroll_clock.current_duration (); + } else { + preroll = 0; + } + + if (postroll_button.get_active()) { + postroll = ARDOUR_UI::instance()->postroll_clock.current_duration (); + } else { + postroll = 0; + } + + if ((left_start_offset = xfade.out().length() - xfade.length()) >= preroll) { + left_start_offset -= preroll; + } + + length = 0; + + if ((left_length = xfade.length()) < xfade.out().length() - left_start_offset) { + length += postroll; + } + + right_length = xfade.length(); + + if (xfade.in().length() - right_length < postroll) { + right_length += postroll; + } + + AudioRegion* left = new AudioRegion (xfade.out(), left_start_offset, left_length, "xfade out", + 0, Region::DefaultFlags, false); + AudioRegion* right = new AudioRegion (xfade.in(), 0, right_length, "xfade in", + 0, Region::DefaultFlags, false); + + pl.add_region (*left, 0); + pl.add_region (*right, 1+preroll); + + /* there is only one ... */ + + pl.foreach_crossfade (this, &CrossfadeEditor::setup); + + session.audition_playlist (); +} + +void +CrossfadeEditor::audition_left_dry () +{ + AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left", + 0, Region::DefaultFlags, false); + + session.audition_region (*left); +} + +void +CrossfadeEditor::audition_left () +{ + AudioPlaylist& pl (session.the_auditioner().prepare_playlist()); + + AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade left", + 0, Region::DefaultFlags, false); + AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in", + 0, Region::DefaultFlags, false); + + pl.add_region (*left, 0); + pl.add_region (*right, 1); + + right->set_muted (true); + + /* there is only one ... */ + + pl.foreach_crossfade (this, &CrossfadeEditor::setup); + + session.audition_playlist (); + + /* memory leak for regions */ +} + +void +CrossfadeEditor::audition_right_dry () +{ + AudioRegion* right = new AudioRegion (xfade.in(), 0, xfade.length(), "xfade in", + 0, Region::DefaultFlags, false); + session.audition_region (*right); +} + +void +CrossfadeEditor::audition_right () +{ + AudioPlaylist& pl (session.the_auditioner().prepare_playlist()); + + AudioRegion* left = new AudioRegion (xfade.out(), xfade.out().length() - xfade.length(), xfade.length(), "xfade out", + 0, Region::DefaultFlags, false); + AudioRegion* right = new AudioRegion (xfade.out(), 0, xfade.length(), "xfade out", + 0, Region::DefaultFlags, false); + + pl.add_region (*left, 0); + pl.add_region (*right, 1); + + left->set_muted (true); + + /* there is only one ... */ + + pl.foreach_crossfade (this, &CrossfadeEditor::setup); + + session.audition_playlist (); +} + +void +CrossfadeEditor::cancel_audition () +{ + session.cancel_audition (); +} + +void +CrossfadeEditor::audition_toggled () +{ + bool x; + + if ((x = audition_both_button.get_active ()) != session.is_auditioning()) { + + if (x) { + audition_both (); + } else { + cancel_audition (); + } + } +} + +void +CrossfadeEditor::audition_right_toggled () +{ + bool x; + + if ((x = audition_right_button.get_active ()) != session.is_auditioning()) { + + if (x) { + audition_right (); + } else { + cancel_audition (); + } + } +} + +void +CrossfadeEditor::audition_right_dry_toggled () +{ + bool x; + + if ((x = audition_right_dry_button.get_active ()) != session.is_auditioning()) { + + if (x) { + audition_right_dry (); + } else { + cancel_audition (); + } + } +} + +void +CrossfadeEditor::audition_left_toggled () +{ + bool x; + + if ((x = audition_left_button.get_active ()) != session.is_auditioning()) { + + if (x) { + audition_left (); + } else { + cancel_audition (); + } + } +} + +void +CrossfadeEditor::audition_left_dry_toggled () +{ + bool x; + + if ((x = audition_left_dry_button.get_active ()) != session.is_auditioning()) { + + if (x) { + audition_left_dry (); + } else { + cancel_audition (); + } + } +} diff --git a/gtk2_ardour/crossfade_edit.h b/gtk2_ardour/crossfade_edit.h new file mode 100644 index 0000000000..dbe62dea66 --- /dev/null +++ b/gtk2_ardour/crossfade_edit.h @@ -0,0 +1,195 @@ +#ifndef __gtk_ardour_xfade_edit_h__ +#define __gtk_ardour_xfade_edit_h__ + +#include + +#include +#include +#include +#include + +#include +#include "ardour_dialog.h" + +namespace ARDOUR +{ + class Session; + class Curve; + class Crossfade; +} + +class CrossfadeEditor : public ArdourDialog +{ + public: + CrossfadeEditor (ARDOUR::Session&, ARDOUR::Crossfade&, double miny, double maxy); + ~CrossfadeEditor (); + + void apply (); + + static const double canvas_border; + + /* these are public so that a caller/subclass can make them do the right thing. + */ + + Gtk::Button cancel_button; + Gtk::Button ok_button; + + struct PresetPoint { + double x; + double y; + + PresetPoint (double a, double b) + : x (a), y (b) {} + }; + + struct Preset : public list { + const gchar** xpm; + + Preset (const gchar** x) + : xpm (x) {} + }; + + typedef list Presets; + + static Presets* fade_in_presets; + static Presets* fade_out_presets; + + private: + ARDOUR::Crossfade& xfade; + ARDOUR::Session& session; + + Gtk::VBox vpacker; + + struct Point { + ~Point(); + + GtkCanvasItem* box; + GtkCanvasItem* curve; + double x; + double y; + + static const int32_t size; + + void move_to (double x, double y, double xfract, double yfract); + }; + + struct PointSorter + { + bool operator() (const CrossfadeEditor::Point* a, const CrossfadeEditor::Point *b) { + return a->x < b->x; + } + }; + + GtkWidget* _canvas; + GtkCanvasItem* toplevel; + Gtk::Widget* canvas; + + struct Half { + GtkCanvasItem* line; + GtkCanvasItem* shading; + list points; + ARDOUR::Curve normative_curve; /* 0 - 1.0, linear */ + ARDOUR::Curve gain_curve; /* 0 - 2.0, gain mapping */ + vector waves; + + Half(); + }; + + enum WhichFade { + In = 0, + Out = 1 + }; + + Half fade[2]; + WhichFade current; + + bool point_grabbed; + vector fade_out_buttons; + vector fade_in_buttons; + + Gtk::HBox action_box; + + Gtk::VBox vpacker2; + + Gtk::Button clear_button; + Gtk::Button revert_button; + + Gtk::ToggleButton audition_both_button; + Gtk::ToggleButton audition_left_dry_button; + Gtk::ToggleButton audition_left_button; + Gtk::ToggleButton audition_right_dry_button; + Gtk::ToggleButton audition_right_button; + + Gtk::ToggleButton preroll_button; + Gtk::ToggleButton postroll_button; + + Gtk::HBox roll_box; + + gint event_handler (GdkEvent*); + + static gint _canvas_event (GtkCanvasItem*, GdkEvent* event, gpointer data); + static gint _point_event (GtkCanvasItem*, GdkEvent* event, gpointer data); + static gint _curve_event (GtkCanvasItem*, GdkEvent* event, gpointer data); + + gint canvas_event (GtkCanvasItem*, GdkEvent* event); + gint point_event (GtkCanvasItem*, GdkEvent* event); + gint curve_event (GtkCanvasItem*, GdkEvent* event); + + void canvas_allocation (GtkAllocation*); + void add_control_point (double x, double y); + Point* make_point (); + void redraw (); + + double effective_width () const { return _canvas->allocation.width - (2.0 * canvas_border); } + double effective_height () const { return _canvas->allocation.height - (2.0 * canvas_border); } + + void clear (); + void reset (); + + double miny; + double maxy; + + Gtk::Table fade_in_table; + Gtk::Table fade_out_table; + + void build_presets (); + void apply_preset (Preset*); + + Gtk::RadioButton select_in_button; + Gtk::RadioButton select_out_button; + Gtk::HBox curve_button_box; + Gtk::HBox audition_box; + + void curve_select_clicked (WhichFade); + + double x_coordinate (double& xfract) const; + double y_coordinate (double& yfract) const; + + void set (const ARDOUR::Curve& alist, WhichFade); + + void make_waves (ARDOUR::AudioRegion&, WhichFade); + void peaks_ready (ARDOUR::AudioRegion* r, WhichFade); + + void _apply_to (ARDOUR::Crossfade* xf); + void setup (ARDOUR::Crossfade*); + void cancel_audition (); + void audition_state_changed (bool); + + void audition_toggled (); + void audition_right_toggled (); + void audition_right_dry_toggled (); + void audition_left_toggled (); + void audition_left_dry_toggled (); + + void audition_both (); + void audition_left_dry (); + void audition_left (); + void audition_right_dry (); + void audition_right (); + + void xfade_changed (ARDOUR::Change); + + void dump (); +}; + +#endif /* __gtk_ardour_xfade_edit_h__ */ diff --git a/gtk2_ardour/crossfade_view.cc b/gtk2_ardour/crossfade_view.cc new file mode 100644 index 0000000000..e074e7626c --- /dev/null +++ b/gtk2_ardour/crossfade_view.cc @@ -0,0 +1,263 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include +#include + +#include "canvas-simplerect.h" +#include "canvas-curve.h" +#include "crossfade_view.h" +#include "rgb_macros.h" +#include "audio_time_axis.h" +#include "public_editor.h" +#include "regionview.h" +#include "utils.h" + +using namespace SigC; +using namespace ARDOUR; +using namespace Editing; + +SigC::Signal1 CrossfadeView::GoingAway; + +CrossfadeView::CrossfadeView (GtkCanvasGroup *parent, + AudioTimeAxisView &tv, + Crossfade& xf, + double spu, + GdkColor& basic_color, + AudioRegionView& lview, + AudioRegionView& rview) + + + : TimeAxisViewItem ("xf.name()", parent, tv, spu, basic_color, xf.position(), + xf.overlap_length(), TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowFrame)), + crossfade (xf), + left_view (lview), + right_view (rview) + +{ + _valid = true; + _visible = true; + + fade_in = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_line_get_type(), + "fill_color_rgba", color_map[cCrossfadeLine], + "width_pixels", (guint) 1, + NULL); + + fade_out = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_line_get_type(), + "fill_color_rgba", color_map[cCrossfadeLine], + "width_pixels", (guint) 1, + NULL); + + set_height (get_time_axis_view().height); + + /* no frame around the xfade or overlap rects */ + + gtk_canvas_item_set (frame, "outline_what", 0, NULL); + + /* never show the vestigial frame */ + + gtk_canvas_item_hide (vestigial_frame); + show_vestigial = false; + + gtk_object_set_data (GTK_OBJECT(group), "crossfadeview", this); + gtk_signal_connect (GTK_OBJECT(group), "event", + (GtkSignalFunc) PublicEditor::canvas_crossfade_view_event, + this); + + crossfade_changed (Change (~0)); + + crossfade.StateChanged.connect (slot (*this, &CrossfadeView::crossfade_changed)); +} + +CrossfadeView::~CrossfadeView () +{ + GoingAway (this) ; /* EMIT_SIGNAL */ +} + +std::string +CrossfadeView::get_item_name () +{ + return "xfade"; +// return crossfade.name(); +} + +void +CrossfadeView::reset_width_dependent_items (double pixel_width) +{ + TimeAxisViewItem::reset_width_dependent_items (pixel_width); + + active_changed (); + + if (pixel_width < 5) { + gtk_canvas_item_hide (fade_in); + gtk_canvas_item_hide (fade_out); + } +} + +void +CrossfadeView::set_height (double height) +{ + if (height == TimeAxisView::Smaller || + height == TimeAxisView::Small) + TimeAxisViewItem::set_height (height - 3 ); + else + TimeAxisViewItem::set_height (height - NAME_HIGHLIGHT_SIZE - 3 ); + + redraw_curves (); +} + +void +CrossfadeView::crossfade_changed (Change what_changed) +{ + bool need_redraw_curves = false; + + if (what_changed & BoundsChanged) { + set_position (crossfade.position(), this); + set_duration (crossfade.overlap_length(), this); + need_redraw_curves = true; + } + + if (what_changed & Crossfade::ActiveChanged) { + /* calls redraw_curves */ + active_changed (); + } else if (need_redraw_curves) { + redraw_curves (); + } +} + +void +CrossfadeView::redraw_curves () +{ + GtkCanvasPoints* points; + int32_t npoints; + float* vec; + + double h; + + /* + At "height - 3.0" the bottom of the crossfade touches the name highlight or the bottom of the track (if the + track is either Small or Smaller. + */ + switch(get_time_axis_view().height) { + case TimeAxisView::Smaller: + case TimeAxisView::Small: + h = get_time_axis_view().height - 3.0; + break; + + default: + h = get_time_axis_view().height - NAME_HIGHLIGHT_SIZE - 3.0; + } + + if (h < 0) { + /* no space allocated yet */ + return; + } + + npoints = get_time_axis_view().editor.frame_to_pixel (crossfade.length()); + npoints = std::min (gdk_screen_width(), npoints); + + if (!_visible || !crossfade.active() || npoints < 3) { + gtk_canvas_item_hide (fade_in); + gtk_canvas_item_hide (fade_out); + return; + } else { + gtk_canvas_item_show (fade_in); + gtk_canvas_item_show (fade_out); + } + + points = get_canvas_points ("xfade edit redraw", npoints); + vec = new float[npoints]; + + crossfade.fade_in().get_vector (0, crossfade.length(), vec, npoints); + for (int i = 0, pci = 0; i < npoints; ++i) { + points->coords[pci++] = i; + points->coords[pci++] = 2.0 + h - (h * vec[i]); + } + gtk_canvas_item_set (fade_in, "points", points, NULL); + + crossfade.fade_out().get_vector (0, crossfade.length(), vec, npoints); + for (int i = 0, pci = 0; i < npoints; ++i) { + points->coords[pci++] = i; + points->coords[pci++] = 2.0 + h - (h * vec[i]); + } + gtk_canvas_item_set (fade_out, "points", points, NULL); + + delete [] vec; + + gtk_canvas_points_unref (points); + + /* XXX this is ugly, but it will have to wait till Crossfades are reimplented + as regions. This puts crossfade views on top of a track, above all regions. + */ + + gtk_canvas_item_raise_to_top (group); +} + +void +CrossfadeView::active_changed () +{ + if (crossfade.active()) { + gtk_canvas_item_set (frame, "fill_color_rgba", color_map[cActiveCrossfade], NULL); + } else { + gtk_canvas_item_set (frame, "fill_color_rgba", color_map[cInactiveCrossfade], NULL); + } + + redraw_curves (); +} + +void +CrossfadeView::set_valid (bool yn) +{ + _valid = yn; +} + +AudioRegionView& +CrossfadeView::upper_regionview () const +{ + if (left_view.region.layer() > right_view.region.layer()) { + return left_view; + } else { + return right_view; + } +} + +void +CrossfadeView::show () +{ + gtk_canvas_item_show (group); + _visible = true; +} + +void +CrossfadeView::hide () +{ + gtk_canvas_item_hide (group); + _visible = false; +} + +void +CrossfadeView::fake_hide () +{ + gtk_canvas_item_hide (group); +} diff --git a/gtk2_ardour/crossfade_view.h b/gtk2_ardour/crossfade_view.h new file mode 100644 index 0000000000..3825a50acf --- /dev/null +++ b/gtk2_ardour/crossfade_view.h @@ -0,0 +1,84 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __gtk_ardour_crossfade_view_h__ +#define __gtk_ardour_crossfade_view_h__ + +#include +#include +#include +#include +#include + +#include "time_axis_view_item.h" + +class AudioTimeAxisView; +class AudioRegionView; + +struct CrossfadeView : public TimeAxisViewItem +{ + CrossfadeView (GtkCanvasGroup*, + AudioTimeAxisView&, + ARDOUR::Crossfade&, + double initial_samples_per_unit, + GdkColor& basic_color, + AudioRegionView& leftview, + AudioRegionView& rightview); + ~CrossfadeView (); + + ARDOUR::Crossfade& crossfade; // ok, let 'em have it + AudioRegionView& left_view; // and these too + AudioRegionView& right_view; + + std::string get_item_name(); + void set_height (double); + + bool valid() const { return _valid; } + bool visible() const { return _visible; } + void set_valid (bool yn); + + static SigC::Signal1 GoingAway; + + AudioRegionView& upper_regionview () const; + + void fake_hide (); + void hide (); + void show (); + + protected: + void reset_width_dependent_items (double pixel_width); + + private: + bool _valid; + bool _visible; + + double spu; + + GtkCanvasItem *overlap_rect; + GtkCanvasItem *fade_in; + GtkCanvasItem *fade_out; + GtkCanvasItem *active_button; + + void crossfade_changed (ARDOUR::Change); + void active_changed (); + void redraw_curves (); +}; + +#endif /* __gtk_ardour_crossfade_view_h__ */ diff --git a/gtk2_ardour/crossfade_xpms.h b/gtk2_ardour/crossfade_xpms.h new file mode 100644 index 0000000000..4b5d0efccd --- /dev/null +++ b/gtk2_ardour/crossfade_xpms.h @@ -0,0 +1,316 @@ +#ifndef __ardour_gtk_crossfade_xpms_h_ +#define __ardour_gtk_crossfade_xpms_h_ + +/* XPM */ +static const gchar * hiout_xpm[] = { +"25 25 3 1", +" c None", +". c #F6F92A", +"+ c #F6FA2A", +" ", +" ", +" ", +" ", +" .+++++++ ", +" .++++++++ ", +" ++++++ ", +" +++++ ", +" ++++ ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" ++ ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" .+. ", +" ", +" ", +" "}; +/* XPM */ +static const gchar * regout2_xpm[] = { +"25 25 3 1", +" c None", +". c #FDFD00", +"+ c #FEFE00", +" ", +" ", +" .+. ", +" +++ ", +" +++ ", +" +++ ", +" .++ ", +" ++ ", +" ++. ", +" +++ ", +" .++ ", +" +++ ", +" +++ ", +" .+++ ", +" ++++ ", +" ++++ ", +" +++++. ", +" .+++++. ", +" .++++++. ", +" .+++++ ", +" .+. ", +" ", +" ", +" ", +" "}; +/* XPM */ +static const gchar * regout_xpm[] = { +"25 25 3 1", +" c None", +". c #FDFD00", +"+ c #FEFE00", +" ", +" ", +" ", +" ", +" .++++. ", +" .++++++. ", +" .+++++. ", +" .+++++ ", +" ++++ ", +" ++++ ", +" ++++ ", +" +++. ", +" +++ ", +" ++. ", +" +++ ", +" .++. ", +" +++ ", +" .++ ", +" ++ ", +" ++ ", +" ++ ", +" .. ", +" ", +" ", +" "}; +/* XPM */ +static const gchar * regin2_xpm[] = { +"25 25 3 1", +" c None", +". c #FDFD00", +"+ c #FEFE00", +" ", +" ", +" .+. ", +" +++ ", +" +++ ", +" ++. ", +" .++ ", +" +++ ", +" ++. ", +" .++ ", +" +++ ", +" .++. ", +" +++ ", +" +++. ", +" ++++ ", +" .++++ ", +" .+++++ ", +" .++++++. ", +" .++++++. ", +" ++++. ", +" .. ", +" ", +" ", +" ", +" "}; +/* XPM */ +static const gchar * regin_xpm[] = { +"25 25 3 1", +" c None", +". c #FDFD00", +"+ c #FEFE00", +" ", +" ", +" ", +" ", +" .++++. ", +" .++++++. ", +" .+++++. ", +" +++++. ", +" ++++ ", +" ++++ ", +" ++++ ", +" .+++ ", +" +++ ", +" .++ ", +" +++ ", +" .++. ", +" +++ ", +" ++. ", +" ++ ", +" ++ ", +" ++ ", +" .. ", +" ", +" ", +" "}; +/* XPM */ +static const gchar * linout_xpm[] = { +"25 25 3 1", +" c None", +". c #FDFD00", +"+ c #FEFE00", +" ", +" ", +" ", +" .. ", +" +++ ", +" .+++ ", +" ++++ ", +" ++++ ", +" +++. ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" .+++ ", +" ++++ ", +" ++++ ", +" ++++ ", +" ++++ ", +" .. ", +" ", +" ", +" "}; +/* XPM */ +static const gchar * linin_xpm[] = { +"25 25 3 1", +" c None", +". c #FDFD00", +"+ c #FEFE00", +" ", +" ", +" ", +" ", +" .+. ", +" +++. ", +" ++++ ", +" ++++ ", +" ++++ ", +" ++++ ", +" +++. ", +" +++ ", +" +++ ", +" +++ ", +" .+++ ", +" ++++ ", +" ++++ ", +" ++++ ", +" ++++ ", +" .+++ ", +" .++ ", +" + ", +" ", +" ", +" "}; +/* XPM */ +static const gchar * loout_xpm[] = { +"25 25 3 1", +" c None", +". c #F6F92A", +"+ c #F6FA2A", +" ", +" ", +" .. ", +" ++ ", +" ++ ", +" ++ ", +" ++ ", +" ++ ", +" +++ ", +" +++ ", +" +++ ", +" ++++ ", +" +++ ", +" +++ ", +" +++ ", +" ++++ ", +" +++++ ", +" ++++++ ", +" +++++++++. ", +" ++++++++ ", +" ++++. ", +" ", +" ", +" ", +" "}; +/* XPM */ +static const gchar * loin_xpm[] = { +"25 25 3 1", +" c None", +". c #F6F92A", +"+ c #F6FA2A", +" ", +" ", +" .+. ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" ++ ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" +++ ", +" ++++ ", +" +++++ ", +" ++++++ ", +" .++++++++ ", +" .+++++++ ", +" ", +" ", +" ", +" ", +" "}; +/* XPM */ +static const gchar * hiin_xpm[] = { +"25 25 3 1", +" c None", +". c #F6FA2A", +"+ c #F6F92A", +" ", +" ", +" ", +" ", +" .......+ ", +" ........+ ", +" ...... ", +" ..... ", +" .... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" ... ", +" .. ", +" ... ", +" ... ", +" ... ", +" ... ", +" +.+ ", +" ", +" ", +" "}; + + +#endif /* __ardour_gtk_crossfade_xpms_h_ */ diff --git a/gtk2_ardour/curvetest.cc b/gtk2_ardour/curvetest.cc new file mode 100644 index 0000000000..613835aa4c --- /dev/null +++ b/gtk2_ardour/curvetest.cc @@ -0,0 +1,51 @@ +#include +#include +#include +#include + +#include + +using namespace std; +using namespace ARDOUR; + +int +curvetest (string filename) +{ + ifstream in (filename.c_str()); + stringstream line; + Curve c (-1.0, +1.0, 0, true); + double minx = DBL_MAX; + double maxx = DBL_MIN; + + while (in) { + double x, y; + + in >> x; + in >> y; + + if (!in) { + break; + } + + if (x < minx) { + minx = x; + } + + if (x > maxx) { + maxx = x; + } + + c.add (x, y); + } + + + float foo[1024]; + + c.get_vector (minx, maxx, foo, 1024); + + for (int i = 0; i < 1024; ++i) { + cout << minx + (((double) i / 1024.0) * (maxx - minx)) << ' ' << foo[i] << endl; + } + + return 0; +} diff --git a/gtk2_ardour/default_keys.cc b/gtk2_ardour/default_keys.cc new file mode 100644 index 0000000000..d8b9a2ae9e --- /dev/null +++ b/gtk2_ardour/default_keys.cc @@ -0,0 +1,113 @@ +/* + Copyright (C) 1999 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include "ardour_ui.h" +#include "keyboard_target.h" + +using namespace ARDOUR; +using namespace Gtkmmext; +using namespace Gtk; +using namespace SigC; + +void +ARDOUR_UI::install_keybindings () +{ + KeyboardTarget::add_action ("start-prefix", slot (*this, &ARDOUR_UI::start_keyboard_prefix)); + + KeyboardTarget::add_action ("toggle-editor-window", slot (*this, &ARDOUR_UI::goto_editor_window)); + KeyboardTarget::add_action ("toggle-mixer-window", slot (*this, &ARDOUR_UI::goto_mixer_window)); + KeyboardTarget::add_action ("toggle-locations-window", slot (*this, &ARDOUR_UI::toggle_location_window)); + KeyboardTarget::add_action ("toggle-big-clock-window", slot (*this, &ARDOUR_UI::toggle_big_clock_window)); + KeyboardTarget::add_action ("toggle-options-window", slot (*this, &ARDOUR_UI::toggle_options_window)); + KeyboardTarget::add_action ("toggle-auto-loop", slot (*this, &ARDOUR_UI::toggle_session_auto_loop)); + KeyboardTarget::add_action ("toggle-punch-in", slot (*this, &ARDOUR_UI::toggle_session_punch_in)); + + KeyboardTarget::add_action ("new-session", bind (slot (*this, &ARDOUR_UI::new_session), false, string())); + KeyboardTarget::add_action ("add-audio-track", bind (slot (*this, &ARDOUR_UI::session_add_audio_track), 1, 1)); + KeyboardTarget::add_action ("add-audio-bus", bind (slot (*this, &ARDOUR_UI::session_add_audio_bus), 1, 1)); + + KeyboardTarget::add_action ("save-state", bind (slot (*this, &ARDOUR_UI::save_state), string (""))); + KeyboardTarget::add_action ("quit", (slot (*this, &ARDOUR_UI::finish))); + + KeyboardTarget::add_action ("remove-last-capture", slot (*this, &ARDOUR_UI::remove_last_capture)); + + KeyboardTarget::add_action ("transport-stop", slot (*this, &ARDOUR_UI::transport_stop)); + KeyboardTarget::add_action ("transport-stop-and-forget-capture", slot (*this, &ARDOUR_UI::transport_stop_and_forget_capture)); + KeyboardTarget::add_action ("transport-roll", slot (*this, &ARDOUR_UI::transport_roll)); + KeyboardTarget::add_action ("transport-loop", slot (*this, &ARDOUR_UI::transport_loop)); + KeyboardTarget::add_action ("transport-record", slot (*this, &ARDOUR_UI::transport_record)); + KeyboardTarget::add_action ("transport-rewind", bind (slot (*this, &ARDOUR_UI::transport_rewind), 0)); + KeyboardTarget::add_action ("transport-rewind-slow", bind (slot (*this, &ARDOUR_UI::transport_rewind), -1)); + KeyboardTarget::add_action ("transport-rewind-fast", bind (slot (*this, &ARDOUR_UI::transport_rewind), 1)); + KeyboardTarget::add_action ("transport-forward", bind (slot (*this, &ARDOUR_UI::transport_forward), 0)); + KeyboardTarget::add_action ("transport-forward-slow", bind (slot (*this, &ARDOUR_UI::transport_forward), -1)); + KeyboardTarget::add_action ("transport-forward-fast", bind (slot (*this, &ARDOUR_UI::transport_forward), 1)); + + KeyboardTarget::add_action ("transport-goto-start", slot (*this, &ARDOUR_UI::transport_goto_start)); + KeyboardTarget::add_action ("transport-goto-end", slot (*this, &ARDOUR_UI::transport_goto_end)); + + KeyboardTarget::add_action ("send-all-midi-feedback", slot (*this, &ARDOUR_UI::send_all_midi_feedback)); + + KeyboardTarget::add_action ("toggle-record-enable-track1", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 0U)); + KeyboardTarget::add_action ("toggle-record-enable-track2", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 1U)); + KeyboardTarget::add_action ("toggle-record-enable-track3", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 2U)); + KeyboardTarget::add_action ("toggle-record-enable-track4", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 3U)); + KeyboardTarget::add_action ("toggle-record-enable-track5", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 4U)); + KeyboardTarget::add_action ("toggle-record-enable-track6", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 5U)); + KeyboardTarget::add_action ("toggle-record-enable-track7", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 6U)); + KeyboardTarget::add_action ("toggle-record-enable-track8", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 7U)); + KeyboardTarget::add_action ("toggle-record-enable-track9", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 8U)); + KeyboardTarget::add_action ("toggle-record-enable-track10", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 9U)); + KeyboardTarget::add_action ("toggle-record-enable-track11", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 10U)); + KeyboardTarget::add_action ("toggle-record-enable-track12", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 11U)); + KeyboardTarget::add_action ("toggle-record-enable-track13", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 12U)); + KeyboardTarget::add_action ("toggle-record-enable-track14", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 13U)); + KeyboardTarget::add_action ("toggle-record-enable-track15", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 14U)); + KeyboardTarget::add_action ("toggle-record-enable-track16", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 15U)); + KeyboardTarget::add_action ("toggle-record-enable-track17", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 16U)); + KeyboardTarget::add_action ("toggle-record-enable-track18", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 17U)); + KeyboardTarget::add_action ("toggle-record-enable-track19", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 18U)); + KeyboardTarget::add_action ("toggle-record-enable-track20", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 19U)); + KeyboardTarget::add_action ("toggle-record-enable-track21", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 20U)); + KeyboardTarget::add_action ("toggle-record-enable-track22", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 21U)); + KeyboardTarget::add_action ("toggle-record-enable-track23", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 22U)); + KeyboardTarget::add_action ("toggle-record-enable-track24", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 23U)); + KeyboardTarget::add_action ("toggle-record-enable-track25", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 24U)); + KeyboardTarget::add_action ("toggle-record-enable-track26", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 25U)); + KeyboardTarget::add_action ("toggle-record-enable-track27", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 26U)); + KeyboardTarget::add_action ("toggle-record-enable-track28", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 27U)); + KeyboardTarget::add_action ("toggle-record-enable-track29", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 28U)); + KeyboardTarget::add_action ("toggle-record-enable-track30", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 29U)); + KeyboardTarget::add_action ("toggle-record-enable-track31", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 30U)); + KeyboardTarget::add_action ("toggle-record-enable-track32", bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 31U)); + +#if 0 + ADD ME TO ARDOUR RC SOMEDAY + add_binding ("Shift-F1",, bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 0+12U)); + add_binding ("Control-F1",, bind (slot (*this, &ARDOUR_UI::toggle_record_enable), 0+24U)); + add_binding ("Alt-F1",, bind (slot (*this, &ARDOUR_UI::toggle_monitor_enable), 0U)); + add_binding ("Alt-Shift-F1",, bind (slot (*this, &ARDOUR_UI::toggle_monitor_enable), 0+12U)); + add_binding ("Alt-Control-F1",, bind (slot (*this, &ARDOUR_UI::toggle_monitor_enable), 0+24U)); +#endif +} diff --git a/gtk2_ardour/editing.cc b/gtk2_ardour/editing.cc new file mode 100644 index 0000000000..672c1ab741 --- /dev/null +++ b/gtk2_ardour/editing.cc @@ -0,0 +1,104 @@ +#include + +#include "editing.h" + +using namespace std; + +// This involves some cpp magic. --taybin + +#define SNAPTYPE(a) /*empty*/ +#define SNAPMODE(a) /*empty*/ +#define REGIONLISTSORTTYPE(a) /*empty*/ +#define MOUSEMODE(a) /*empty*/ +#define ZOOMFOCUS(a) /*empty*/ +#define DISPLAYCONTROL(a) /*empty*/ + +namespace Editing { + +// SNAPTYPE +#undef SNAPTYPE +#define SNAPTYPE(s) if (!strcmp(type, #s)) {return s;} +SnapType +str2snaptype (string str) { + const char* type = str.c_str(); + #include "editing_syms.h" + return SnapToBar; +} +#undef SNAPTYPE +#define SNAPTYPE(a) /*empty*/ + +// SNAPMODE +#undef SNAPMODE +#define SNAPMODE(s) if (!strcmp(type, #s)) {return s;} +SnapMode +str2snapmode (string str) { + const char* type = str.c_str(); + #include "editing_syms.h" + return SnapNormal; +} +#undef SNAPMODE +#define SNAPMODE(a) /*empty*/ + +// REGIONLISTSORTTYPE +#undef REGIONLISTSORTTYPE +#define REGIONLISTSORTTYPE(s) if (!strcmp(type, #s)) {return s;} +RegionListSortType +str2regionlistsorttype (string str) { + const char* type = str.c_str(); + #include "editing_syms.h" + return ByName; +} +#undef REGIONLISTSORTTYPE +#define REGIONLISTSORTTYPE(a) /*empty*/ + +// MOUSEMODE +#undef MOUSEMODE +#define MOUSEMODE(s) if (!strcmp(type, #s)) {return s;} +MouseMode +str2mousemode (string str) { + const char* type = str.c_str(); + #include "editing_syms.h" + return MouseObject; +} +#undef MOUSEMODE +#define MOUSEMODE(a) /*empty*/ + +// ZOOMFOCUS +#undef ZOOMFOCUS +#define ZOOMFOCUS(s) if (!strcmp(type, #s)) {return s;} +ZoomFocus +str2zoomfocus (string str) { + const char* type = str.c_str(); + #include "editing_syms.h" + return ZoomFocusPlayhead; +} +#undef ZOOMFOCUS +#define ZOOMFOCUS(a) /*empty*/ + +// DISPLAYCONTROL +#undef DISPLAYCONTROL +#define DISPLAYCONTROL(s) if (!strcmp(type, #s)) {return s;} +DisplayControl +str2displaycontrol (string str) { + const char* type = str.c_str(); + #include "editing_syms.h" + return FollowPlayhead; +} +#undef DISPLAYCONTROL +#define DISPLAYCONTROL(a) /*empty*/ + +// COLORID +#undef COLORID +#define COLORID(s) if (!strcmp(type, #s)) {return s;} +ColorID +str2color_id (string str) { + const char* type = str.c_str(); + #include "editing_syms.h" + return cFrameHandleEndOutline; +} +#undef COLORID +#define COLORID(a) /*empty*/ + +ColorMap color_map; + +} // namespace Editing diff --git a/gtk2_ardour/editing.h b/gtk2_ardour/editing.h new file mode 100644 index 0000000000..2b95073ef7 --- /dev/null +++ b/gtk2_ardour/editing.h @@ -0,0 +1,170 @@ +#ifndef __gtk_ardour_editing_h__ +#define __gtk_ardour_editing_h__ + +#include +#include + +// This involves some cpp magic. --taybin + +#define SNAPTYPE(a) /*empty*/ +#define SNAPMODE(a) /*empty*/ +#define REGIONLISTSORTTYPE(a) /*empty*/ +#define MOUSEMODE(a) /*empty*/ +#define ZOOMFOCUS(a) /*empty*/ +#define DISPLAYCONTROL(a) /*empty*/ +#define COLORID(a) /*empty*/ + +namespace Editing { + +// SNAPTYPE +#undef SNAPTYPE +#define SNAPTYPE(a) a, +enum SnapType { + #include "editing_syms.h" +}; + +#undef SNAPTYPE +#define SNAPTYPE(s) #s, +static const char *snaptypestrs[] = { + #include "editing_syms.h" +}; +inline const char* enum2str(SnapType m) {return snaptypestrs[m];} +SnapType str2snaptype(std::string); + +#undef SNAPTYPE +#define SNAPTYPE(a) /*empty*/ + +// SNAPMODE +#undef SNAPMODE +#define SNAPMODE(a) a, +enum SnapMode { + #include "editing_syms.h" +}; + +#undef SNAPMODE +#define SNAPMODE(s) #s, +static const char *snapmodestrs[] = { + #include "editing_syms.h" +}; +inline const char* enum2str(SnapMode m) {return snapmodestrs[m];} +SnapMode str2snapmode(std::string); + +#undef SNAPMODE +#define SNAPMODE(a) /*empty*/ + +// REGIONLISTSORTTYPE +#undef REGIONLISTSORTTYPE +#define REGIONLISTSORTTYPE(a) a, +enum RegionListSortType { + #include "editing_syms.h" +}; + +#undef REGIONLISTSORTTYPE +#define REGIONLISTSORTTYPE(s) #s, +static const char *regionlistsorttypestrs[] = { + #include "editing_syms.h" +}; +inline const char* enum2str(RegionListSortType m) {return regionlistsorttypestrs[m];} +RegionListSortType str2regionlistsorttype(std::string); + +#undef REGIONLISTSORTTYPE +#define REGIONLISTSORTTYPE(a) /*empty*/ + +// MOUSEMODE +#undef MOUSEMODE +#define MOUSEMODE(a) a, +enum MouseMode { + #include "editing_syms.h" +}; + +#undef MOUSEMODE +#define MOUSEMODE(s) #s, +static const char *mousemodestrs[] = { + #include "editing_syms.h" +}; +inline const char* enum2str(MouseMode m) {return mousemodestrs[m];} +MouseMode str2mousemode(std::string); + +#undef MOUSEMODE +#define MOUSEMODE(a) /*empty*/ + +// ZOOMFOCUS +#undef ZOOMFOCUS +#define ZOOMFOCUS(a) a, +enum ZoomFocus { + #include "editing_syms.h" +}; + +#undef ZOOMFOCUS +#define ZOOMFOCUS(s) #s, +static const char *zoomfocusstrs[] = { + #include "editing_syms.h" +}; +inline const char* enum2str(ZoomFocus m) {return zoomfocusstrs[m];} +ZoomFocus str2zoomfocus(std::string); + +#undef ZOOMFOCUS +#define ZOOMFOCUS(a) /*empty*/ + +// DISPLAYCONTROL +#undef DISPLAYCONTROL +#define DISPLAYCONTROL(a) a, +enum DisplayControl { + #include "editing_syms.h" +}; + +#undef DISPLAYCONTROL +#define DISPLAYCONTROL(s) #s, +static const char *displaycontrolstrs[] = { + #include "editing_syms.h" +}; +inline const char* enum2str(DisplayControl m) {return displaycontrolstrs[m];} +DisplayControl str2displaycontrol (std::string); + +#undef DISPLAYCONTROL +#define DISPLAYCONTROL(a) /*empty*/ + +#undef COLORID +#define COLORID(a) a, +enum ColorID { + #include "editing_syms.h" +}; + +#undef COLORID +#define COLORID(s) #s, +static const char *color_id_strs[] = { + #include "editing_syms.h" +}; +inline const char* enum2str(ColorID m) {return color_id_strs[m];} +ColorID str2color_id (std::string); + +#undef COLORID +#define COLORID(a) /*empty*/ + +///////////////////// +// These don't need their state saved. yet... +enum CutCopyOp { + Cut, + Copy, + Clear +}; + +enum XFadeType { + Pre, + Post, + At +}; + +struct Color { + char r; + char g; + char b; + char a; +}; + +typedef std::map ColorMap; +extern ColorMap color_map; + +} // namespace Editing + +#endif // __gtk_ardour_editing_h__ diff --git a/gtk2_ardour/editing_syms.h b/gtk2_ardour/editing_syms.h new file mode 100644 index 0000000000..3037daa3e2 --- /dev/null +++ b/gtk2_ardour/editing_syms.h @@ -0,0 +1,157 @@ +/* Changing this order will break the menu */ +SNAPTYPE(SnapToFrame) +SNAPTYPE(SnapToCDFrame) +SNAPTYPE(SnapToSMPTEFrame) +SNAPTYPE(SnapToSMPTESeconds) +SNAPTYPE(SnapToSMPTEMinutes) +SNAPTYPE(SnapToSeconds) +SNAPTYPE(SnapToMinutes) +SNAPTYPE(SnapToAThirtysecondBeat) +SNAPTYPE(SnapToASixteenthBeat) +SNAPTYPE(SnapToAEighthBeat) +SNAPTYPE(SnapToAQuarterBeat) +SNAPTYPE(SnapToAThirdBeat) +SNAPTYPE(SnapToBeat) +SNAPTYPE(SnapToBar) +SNAPTYPE(SnapToMark) +SNAPTYPE(SnapToEditCursor) +SNAPTYPE(SnapToRegionStart) +SNAPTYPE(SnapToRegionEnd) +SNAPTYPE(SnapToRegionSync) +SNAPTYPE(SnapToRegionBoundary) + +/* Changing this order will break the menu */ +SNAPMODE(SnapNormal) +SNAPMODE(SnapMagnetic) + +REGIONLISTSORTTYPE(ByEndInFile) +REGIONLISTSORTTYPE(ByLength) +REGIONLISTSORTTYPE(ByName) +REGIONLISTSORTTYPE(ByPosition) +REGIONLISTSORTTYPE(BySourceFileCreationDate) +REGIONLISTSORTTYPE(BySourceFileFS) +REGIONLISTSORTTYPE(BySourceFileLength) +REGIONLISTSORTTYPE(BySourceFileName) +REGIONLISTSORTTYPE(ByStartInFile) +REGIONLISTSORTTYPE(ByTimestamp) + +MOUSEMODE(MouseGain) +MOUSEMODE(MouseObject) +MOUSEMODE(MouseRange) +MOUSEMODE(MouseTimeFX) +MOUSEMODE(MouseZoom) +MOUSEMODE(MouseAudition) + +/* Changing this order will break the menu */ +ZOOMFOCUS(ZoomFocusLeft) +ZOOMFOCUS(ZoomFocusRight) +ZOOMFOCUS(ZoomFocusCenter) +ZOOMFOCUS(ZoomFocusPlayhead) +ZOOMFOCUS(ZoomFocusEdit) + +DISPLAYCONTROL(FollowPlayhead) +DISPLAYCONTROL(ShowMeasures) +DISPLAYCONTROL(ShowWaveforms) +DISPLAYCONTROL(ShowWaveformsRecording) + +COLORID(cWaveForm) +COLORID(cMutedWaveForm) +COLORID(cSelectedFrameBase) +COLORID(cFrameBase) +COLORID(cAudioTrackBase) +COLORID(cAudioTrackOutline) +COLORID(cAudioBusBase) +COLORID(cTimeStretchFill) +COLORID(cTimeStretchOutline) +COLORID(cAutomationLine) +COLORID(cLeftPanAutomationLine) +COLORID(cRightPanAutomationLine) +COLORID(cRedirectAutomationLine) +COLORID(cControlPointFill) +COLORID(cControlPointOutline) +COLORID(cEnteredControlPointOutline) +COLORID(cEnteredControlPointSelected) +COLORID(cEnteredControlPoint) +COLORID(cControlPointSelected) +COLORID(cControlPoint) +COLORID(cAutomationTrackFill) +COLORID(cAutomationTrackOutline) +COLORID(cCrossfadeEditorBase) +COLORID(cCrossfadeEditorLine) +COLORID(cSelectedCrossfadeEditorLine) +COLORID(cCrossfadeEditorLineShading) +COLORID(cCrossfadeEditorPointFill) +COLORID(cCrossfadeEditorPointOutline) +COLORID(cCrossfadeEditorWave) +COLORID(cSelectedCrossfadeEditorWave) +COLORID(cCrossfadeLine) +COLORID(cActiveCrossfade) +COLORID(cInactiveCrossfade) +COLORID(cLocationMarker) +COLORID(cLocationRange) +COLORID(cLocationCDMarker) +COLORID(cLocationLoop) +COLORID(cLocationPunch) +COLORID(cVerboseCanvasCursor) +COLORID(cTempoBar) +COLORID(cMeterBar) +COLORID(cMarkerBar) +COLORID(cRangeMarkerBar) +COLORID(cTransportMarkerBar) +COLORID(cRangeDragBarRect) +COLORID(cRangeDragBarRectFill) +COLORID(cRangeDragRect) +COLORID(cRangeDragRectFill) +COLORID(cTransportDragRect) +COLORID(cTransportDragRectFill) +COLORID(cMarkerDragLine) +COLORID(cTransportLoopRect) +COLORID(cTransportLoopRectFill) +COLORID(cTransportPunchRect) +COLORID(cTransportPunchRectFill) +COLORID(cPunchInLine) +COLORID(cPunchOutLine) +COLORID(cZoomRect) +COLORID(cZoomRectFill) +COLORID(cRubberBandRect) +COLORID(cRubberBandRectFill) +COLORID(cFirstActionMessage) +COLORID(cEnteredGainLine) +COLORID(cEnteredAutomationLine) +COLORID(cEnteredMarker) +COLORID(cMeterMarker) +COLORID(cTempoMarker) +COLORID(cMeasureLineBeat) +COLORID(cMeasureLineBar) +COLORID(cGhostTrackBaseOutline) +COLORID(cGhostTrackBaseFill) +COLORID(cGhostTrackWave) +COLORID(cImageTrackBase) +COLORID(cImageTrackOutline) +COLORID(cMarkerTrackBase) +COLORID(cMarkerTrackOutline) +COLORID(cZeroLine) +COLORID(cGainLine) +COLORID(cGainLineInactive) +COLORID(cRecordingRectFill) +COLORID(cRecordingRectOutline) +COLORID(cSelectionRectFill) +COLORID(cSelectionRectOutline) +COLORID(cSelectionEndFill) +COLORID(cSelectionEndOutline) +COLORID(cSelectionStartFill) +COLORID(cSelectionStartOutline) +COLORID(cVestigialFrameFill) +COLORID(cVestigialFrameOutline) +COLORID(cTimeAxisFrameFill) +COLORID(cTimeAxisFrameOutline) +COLORID(cNameHighlightFill) +COLORID(cNameHighlightOutline) +COLORID(cFrameHandleStartFill) +COLORID(cFrameHandleStartOutline) +COLORID(cFrameHandleEndFill) +COLORID(cFrameHandleEndOutline) +COLORID(cTrimHandleLockedStart) +COLORID(cTrimHandleLockedEnd) +COLORID(cTrimHandleStart) +COLORID(cTrimHandleEnd) diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc new file mode 100644 index 0000000000..2bd016e8b7 --- /dev/null +++ b/gtk2_ardour/editor.cc @@ -0,0 +1,4655 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ardour_ui.h" +#include "canvas-ruler.h" +#include "canvas-simpleline.h" +#include "canvas-simplerect.h" +#include "canvas-waveview.h" +#include "check_mark.h" +#include "editor.h" +#include "grouped_buttons.h" +#include "keyboard.h" +#include "library_ui.h" +#include "marker.h" +#include "playlist_selector.h" +#include "regionview.h" +#include "rgb_macros.h" +#include "selection.h" +#include "streamview.h" +#include "time_axis_view.h" +#include "utils.h" +#include "crossfade_view.h" +#include "editing.h" +#include "public_editor.h" +#include "crossfade_edit.h" +#include "extra_bind.h" +#include "audio_time_axis.h" +#include "gui_thread.h" + +#include "i18n.h" + +/* */ +#include "imageframe_socket_handler.h" +/* */ + +using namespace std; +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; +using namespace Gtkmmext; +using namespace Editing; + +/* XXX this is a hack. it ought to be the maximum value of an jack_nframes_t */ + +const double max_canvas_coordinate = 100000000.0; +const double Editor::timebar_height = 15.0; + +#include "editor_xpms" + +static const gchar *route_list_titles[] = { + N_("Tracks"), + 0 +}; + +static const gchar *edit_group_list_titles[] = { + "foo", "bar", 0 +}; + +static const gchar *region_list_display_titles[] = { + N_("Regions/name"), + 0 +}; + +static const gchar *named_selection_display_titles[] = { + N_("Chunks"), + 0 +}; + +static const int32_t slide_index = 0; +static const int32_t splice_index = 1; + +static const gchar *edit_mode_strings[] = { + N_("Slide"), + N_("Splice"), + 0 +}; + +static const gchar *snap_type_strings[] = { + N_("None"), + N_("CD Frames"), + N_("SMPTE Frames"), + N_("SMPTE Seconds"), + N_("SMPTE Minutes"), + N_("Seconds"), + N_("Minutes"), + N_("Beats/32"), + N_("Beats/16"), + N_("Beats/8"), + N_("Beats/4"), + N_("Beats/3"), + N_("Beats"), + N_("Bars"), + N_("Marks"), + N_("Edit Cursor"), + N_("Region starts"), + N_("Region ends"), + N_("Region syncs"), + N_("Region bounds"), + 0 +}; + +static const gchar *snap_mode_strings[] = { + N_("Normal"), + N_("Magnetic"), + 0 +}; + +static const gchar *zoom_focus_strings[] = { + N_("Left"), + N_("Right"), + N_("Center"), + N_("Playhead"), + N_("Edit Cursor"), + 0 +}; + +/* Soundfile drag-n-drop */ + +enum { + TARGET_STRING, + TARGET_ROOTWIN, + TARGET_URL +}; + +static GtkTargetEntry target_table[] = { + { "STRING", 0, TARGET_STRING }, + { "text/plain", 0, TARGET_STRING }, + { "text/uri-list", 0, TARGET_URL }, + { "application/x-rootwin-drop", 0, TARGET_ROOTWIN } +}; + +static guint n_targets = sizeof(target_table) / sizeof(target_table[0]); + +GdkCursor* Editor::cross_hair_cursor = 0; +GdkCursor* Editor::selector_cursor = 0; +GdkCursor* Editor::trimmer_cursor = 0; +GdkCursor* Editor::grabber_cursor = 0; +GdkCursor* Editor::zoom_cursor = 0; +GdkCursor* Editor::time_fx_cursor = 0; +GdkCursor* Editor::fader_cursor = 0; +GdkCursor* Editor::speaker_cursor = 0; +GdkCursor* Editor::null_cursor = 0; +GdkCursor* Editor::wait_cursor = 0; +GdkCursor* Editor::timebar_cursor = 0; + +GdkPixmap *Editor::check_pixmap = 0; +GdkBitmap *Editor::check_mask = 0; +GdkPixmap *Editor::empty_pixmap = 0; +GdkBitmap *Editor::empty_mask = 0; + +extern gint route_list_compare_func (GtkCList*,gconstpointer,gconstpointer); + +Editor::Editor (AudioEngine& eng) + : engine (eng), + + /* time display buttons */ + + minsec_label (_("Mins:Secs")), + bbt_label (_("Bars:Beats")), + smpte_label (_("SMPTE")), + frame_label (_("Frames")), + tempo_label (_("Tempo")), + meter_label (_("Meter")), + mark_label (_("Location Markers")), + range_mark_label (_("Range Markers")), + transport_mark_label (_("Loop/Punch Ranges")), + + edit_packer (3, 3, false), + edit_hscroll_left_arrow (GTK_ARROW_LEFT, GTK_SHADOW_OUT), + edit_hscroll_right_arrow (GTK_ARROW_RIGHT, GTK_SHADOW_OUT), + + region_list_display (internationalize (region_list_display_titles)), + + named_selection_display (internationalize (named_selection_display_titles)), + + /* tool bar related */ + + editor_mixer_button (_("editor\nmixer")), + + selection_start_clock (X_("SelectionStartClock"), true), + selection_end_clock (X_("SelectionEndClock"), true), + edit_cursor_clock (X_("EditCursorClock"), true), + zoom_range_clock (X_("ZoomRangeClock"), true, true), + + toolbar_selection_clock_table (2,3), + + mouse_mode_button_table (2, 3), + + mouse_select_button (_("range")), + mouse_move_button (_("object")), + mouse_gain_button (_("gain")), + mouse_zoom_button (_("zoom")), + mouse_timefx_button (_("timefx")), + mouse_audition_button (_("listen")), + + automation_mode_button (_("mode")), + global_automation_button (_("automation")), + + edit_mode_label (_("Edit Mode")), + snap_type_label (_("Snap To")), + snap_mode_label(_("Snap Mode")), + zoom_focus_label (_("Zoom Focus")), + + route_list (internationalize (route_list_titles)), + edit_group_list (internationalize (edit_group_list_titles)), + + /* */ + image_socket_listener(0), + /* */ + + /* nudge */ + + nudge_label (_("Nudge")), + nudge_clock (X_("NudgeClock"), true, true) + +{ + constructed = false; + + /* we are a singleton */ + + PublicEditor::_instance = this; + + init_colormap (); + + check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, + gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gtkobj())), + &check_mask, NULL, (gchar **) check_xpm); + empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, + gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gtkobj())), + &empty_mask, NULL, (gchar **) empty_xpm); + + session = 0; + + selection = new Selection; + cut_buffer = new Selection; + + selection->TimeChanged.connect (slot (*this, &Editor::time_selection_changed)); + selection->TracksChanged.connect (slot (*this, &Editor::track_selection_changed)); + selection->RegionsChanged.connect (slot (*this, &Editor::region_selection_changed)); + selection->PointsChanged.connect (slot (*this, &Editor::point_selection_changed)); + + clicked_regionview = 0; + clicked_trackview = 0; + clicked_audio_trackview = 0; + clicked_crossfadeview = 0; + clicked_control_point = 0; + latest_regionview = 0; + region_list_display_drag_region = 0; + last_update_frame = 0; + drag_info.item = 0; + last_audition_region = 0; + region_list_button_region = 0; + current_mixer_strip = 0; + current_bbt_points = 0; + + snap_type = SnapToFrame; + set_snap_to (snap_type); + snap_mode = SnapNormal; + set_snap_mode (snap_mode); + snap_threshold = 5.0; + bbt_beat_subdivision = 4; + canvas_width = 0; + canvas_height = 0; + autoscroll_timeout_tag = -1; + interthread_progress_window = 0; + current_interthread_info = 0; + _show_measures = true; + _show_waveforms = true; + _show_waveforms_recording = true; + first_action_message = 0; + export_dialog = 0; + show_gain_after_trim = false; + no_zoom_repos_update = false; + need_wave_cursor = 0; + ignore_route_list_reorder = false; + verbose_cursor_on = true; + route_removal = false; + track_spacing = 0; + show_automatic_regions_in_region_list = true; + have_pending_keyboard_selection = false; + _follow_playhead = true; + _xfade_visibility = true; + editor_ruler_menu = 0; + no_ruler_shown_update = false; + edit_group_list_menu = 0; + route_list_menu = 0; + region_list_menu = 0; + marker_menu = 0; + marker_menu_item = 0; + tm_marker_menu = 0; + transport_marker_menu = 0; + new_transport_marker_menu = 0; + editor_mixer_strip_width = Wide; + repos_zoom_queued = false; + import_audio_item = 0; + embed_audio_item = 0; + region_edit_menu_split_item = 0; + temp_location = 0; + region_edit_menu_split_multichannel_item = 0; + edit_hscroll_dragging = false; + leftmost_frame = 0; + ignore_mouse_mode_toggle = false; + current_stepping_trackview = 0; + entered_track = 0; + entered_regionview = 0; + clear_entered_track = false; + _new_regionviews_show_envelope = false; + current_timestretch = 0; + + edit_cursor = 0; + playhead_cursor = 0; + + location_marker_color = color_map[cLocationMarker]; + location_range_color = color_map[cLocationRange]; + location_cd_marker_color = color_map[cLocationCDMarker]; + location_loop_color = color_map[cLocationLoop]; + location_punch_color = color_map[cLocationPunch]; + + range_marker_drag_rect = 0; + marker_drag_line = 0; + + mouse_mode = MouseZoom; /* force change in next call */ + set_mouse_mode (MouseObject, true); + + frames_per_unit = 2048; /* too early to use set_frames_per_unit */ + zoom_focus = ZoomFocusLeft; + zoom_range_clock.ValueChanged.connect (slot (*this, &Editor::zoom_adjustment_changed)); + + initialize_rulers (); + initialize_canvas (); + + track_canvas_scroller.add (*track_canvas); + track_canvas_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_NEVER); + track_canvas_scroller.set_name ("TrackCanvasScroller"); + + track_canvas_scroller.get_vadjustment()->value_changed.connect (slot (*this, &Editor::tie_vertical_scrolling)); + track_canvas_scroller.get_vadjustment()->set_step_increment (10.0); + + track_canvas_scroller.get_hadjustment()->set_lower (0.0); + track_canvas_scroller.get_hadjustment()->set_upper (1200.0); + track_canvas_scroller.get_hadjustment()->set_step_increment (20.0); + track_canvas_scroller.get_hadjustment()->value_changed.connect (slot (*this, &Editor::canvas_horizontally_scrolled)); + + edit_vscrollbar.set_adjustment(track_canvas_scroller.get_vadjustment()); + edit_hscrollbar.set_adjustment(track_canvas_scroller.get_hadjustment()); + + edit_hscrollbar.button_press_event.connect (slot (*this, &Editor::hscroll_slider_button_press)); + edit_hscrollbar.button_release_event.connect (slot (*this, &Editor::hscroll_slider_button_release)); + edit_hscrollbar.size_allocate.connect (slot (*this, &Editor::hscroll_slider_allocate)); + + time_canvas_scroller.add (*time_canvas); + time_canvas_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_NEVER); + time_canvas_scroller.set_hadjustment (track_canvas_scroller.get_hadjustment()); + time_canvas_scroller.set_name ("TimeCanvasScroller"); + + edit_controls_vbox.set_spacing (track_spacing); + edit_controls_hbox.pack_start (edit_controls_vbox, true, true); + edit_controls_scroller.add_with_viewport (edit_controls_hbox); + edit_controls_scroller.set_name ("EditControlsBase"); + edit_controls_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_NEVER); + + Viewport* viewport = static_cast (edit_controls_scroller.get_child()); + + viewport->set_shadow_type (GTK_SHADOW_NONE); + viewport->set_name ("EditControlsBase"); + viewport->add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK); + viewport->button_release_event.connect (slot (*this, &Editor::edit_controls_button_release)); + + build_cursors (); + setup_toolbar (); + + XMLNode* node = ARDOUR_UI::instance()->editor_settings(); + set_state (*node); + + edit_cursor_clock.ValueChanged.connect (slot (*this, &Editor::edit_cursor_clock_changed)); + + time_canvas_vbox.pack_start (*minsec_ruler, false, false); + time_canvas_vbox.pack_start (*smpte_ruler, false, false); + time_canvas_vbox.pack_start (*frames_ruler, false, false); + time_canvas_vbox.pack_start (*bbt_ruler, false, false); + time_canvas_vbox.pack_start (time_canvas_scroller, true, true); + time_canvas_vbox.set_usize (-1, (int)(timebar_height * visible_timebars)); + + bbt_label.set_name ("EditorTimeButton"); + bbt_label.set_usize (-1, (int)timebar_height); + bbt_label.set_alignment (1.0, 0.5); + bbt_label.set_padding (5,0); + minsec_label.set_name ("EditorTimeButton"); + minsec_label.set_usize (-1, (int)timebar_height); + minsec_label.set_alignment (1.0, 0.5); + minsec_label.set_padding (5,0); + smpte_label.set_name ("EditorTimeButton"); + smpte_label.set_usize (-1, (int)timebar_height); + smpte_label.set_alignment (1.0, 0.5); + smpte_label.set_padding (5,0); + frame_label.set_name ("EditorTimeButton"); + frame_label.set_usize (-1, (int)timebar_height); + frame_label.set_alignment (1.0, 0.5); + frame_label.set_padding (5,0); + tempo_label.set_name ("EditorTimeButton"); + tempo_label.set_usize (-1, (int)timebar_height); + tempo_label.set_alignment (1.0, 0.5); + tempo_label.set_padding (5,0); + meter_label.set_name ("EditorTimeButton"); + meter_label.set_usize (-1, (int)timebar_height); + meter_label.set_alignment (1.0, 0.5); + meter_label.set_padding (5,0); + mark_label.set_name ("EditorTimeButton"); + mark_label.set_usize (-1, (int)timebar_height); + mark_label.set_alignment (1.0, 0.5); + mark_label.set_padding (5,0); + range_mark_label.set_name ("EditorTimeButton"); + range_mark_label.set_usize (-1, (int)timebar_height); + range_mark_label.set_alignment (1.0, 0.5); + range_mark_label.set_padding (5,0); + transport_mark_label.set_name ("EditorTimeButton"); + transport_mark_label.set_usize (-1, (int)timebar_height); + transport_mark_label.set_alignment (1.0, 0.5); + transport_mark_label.set_padding (5,0); + + time_button_vbox.pack_start (minsec_label, false, false); + time_button_vbox.pack_start (smpte_label, false, false); + time_button_vbox.pack_start (frame_label, false, false); + time_button_vbox.pack_start (bbt_label, false, false); + time_button_vbox.pack_start (meter_label, false, false); + time_button_vbox.pack_start (tempo_label, false, false); + time_button_vbox.pack_start (mark_label, false, false); + + time_button_event_box.add (time_button_vbox); + + time_button_event_box.set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + time_button_event_box.set_name ("TimebarLabelBase"); + time_button_event_box.button_release_event.connect (slot (*this, &Editor::ruler_label_button_release)); + + /* these enable us to have a dedicated window (for cursor setting, etc.) + for the canvas areas. + */ + + track_canvas_event_box.add (track_canvas_scroller); + + time_canvas_event_box.add (time_canvas_vbox); + time_canvas_event_box.set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK); + + + edit_packer.set_col_spacings (0); + edit_packer.set_row_spacings (0); + edit_packer.set_homogeneous (false); + edit_packer.set_name ("EditorWindow"); + +// edit_packer.attach (edit_hscroll_left_arrow_event, 0, 1, 0, 1, GTK_FILL, 0, 0, 0); +// edit_packer.attach (edit_hscroll_slider, 1, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0, 0, 0); +// edit_packer.attach (edit_hscroll_right_arrow_event, 2, 3, 0, 1, GTK_FILL, 0, 0, 0); + edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0, 0, 0); + + edit_packer.attach (time_button_event_box, 0, 1, 1, 2, GTK_FILL, 0, 0, 0); + edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, GTK_FILL|GTK_EXPAND, 0, 0, 0); + + edit_packer.attach (edit_controls_scroller, 0, 1, 2, 3, GTK_FILL, GTK_FILL|GTK_EXPAND, 0, 0); + edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0); + edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, 0, GTK_FILL|GTK_EXPAND, 0, 0); + + edit_frame.set_name ("BaseFrame"); + edit_frame.set_shadow_type (GTK_SHADOW_IN); + edit_frame.add (edit_packer); + + zoom_in_button.set_name ("EditorTimeButton"); + zoom_out_button.set_name ("EditorTimeButton"); + ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in")); + ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out")); + +// zoom_onetoone_button.set_name ("EditorTimeButton"); + zoom_out_full_button.set_name ("EditorTimeButton"); +// ARDOUR_UI::instance()->tooltips().set_tip (zoom_onetoone_button, _("Zoom in 1:1")); + ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session")); + + zoom_in_button.add (*(manage (new Gtk::Pixmap (zoom_in_button_xpm)))); + zoom_out_button.add (*(manage (new Gtk::Pixmap (zoom_out_button_xpm)))); + zoom_out_full_button.add (*(manage (new Gtk::Pixmap (zoom_out_full_button_xpm)))); +// zoom_onetoone_button.add (*(manage (new Gtk::Pixmap (zoom_onetoone_button_xpm)))); + + + zoom_in_button.clicked.connect (bind (slot (*this, &Editor::temporal_zoom_step), false)); + zoom_out_button.clicked.connect (bind (slot (*this, &Editor::temporal_zoom_step), true)); + zoom_out_full_button.clicked.connect (slot (*this, &Editor::temporal_zoom_session)); +// zoom_onetoone_button.clicked.connect (bind (slot (*this, &Editor::temporal_zoom), 1.0)); + + zoom_indicator_box.pack_start (zoom_out_button, false, false); + zoom_indicator_box.pack_start (zoom_in_button, false, false); + zoom_indicator_box.pack_start (zoom_range_clock, false, false); +// zoom_indicator_box.pack_start (zoom_onetoone_button, false, false); + zoom_indicator_box.pack_start (zoom_out_full_button, false, false); + + zoom_indicator_label.set_text (_("Zoom Span")); + zoom_indicator_label.set_name ("ToolBarLabel"); + + + zoom_indicator_vbox.set_spacing (3); + zoom_indicator_vbox.set_border_width (3); + zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false); + zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false); + + + bottom_hbox.set_border_width (3); + bottom_hbox.set_spacing (3); + + route_list.set_name ("TrackListDisplay"); + route_list.set_usize (75,-1); + route_list.column_titles_active(); + route_list.set_compare_func (route_list_compare_func); + route_list.set_shadow_type (GTK_SHADOW_IN); + route_list.set_selection_mode (GTK_SELECTION_MULTIPLE); + route_list.set_reorderable (true); + edit_group_list.set_usize (75, -1); + + route_list_scroller.add (route_list); + route_list_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + route_list.select_row.connect (slot (*this, &Editor::route_list_selected)); + route_list.unselect_row.connect (slot (*this, &Editor::route_list_unselected)); + route_list.row_move.connect (slot (*this, &Editor::queue_route_list_reordered)); + route_list.click_column.connect (slot (*this, &Editor::route_list_column_click)); + + edit_group_list_button_label.set_text (_("Edit Groups")); + edit_group_list_button_label.set_name ("EditGroupTitleButton"); + edit_group_list_button.add (edit_group_list_button_label); + edit_group_list_button.set_name ("EditGroupTitleButton"); + + edit_group_list.column_titles_hide(); + edit_group_list.set_name ("MixerGroupList"); + edit_group_list.set_shadow_type (GTK_SHADOW_IN); + edit_group_list.set_selection_mode (GTK_SELECTION_MULTIPLE); + edit_group_list.set_reorderable (false); + edit_group_list.set_usize (75, -1); + edit_group_list.set_column_auto_resize (0, true); + edit_group_list.columns_autosize (); + + edit_group_list_scroller.add (edit_group_list); + edit_group_list_scroller.set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + edit_group_list_button.clicked.connect (slot (*this, &Editor::edit_group_list_button_clicked)); + edit_group_list.button_press_event.connect (slot (*this, &Editor::edit_group_list_button_press_event)); + edit_group_list.select_row.connect (slot (*this, &Editor::edit_group_selected)); + edit_group_list.unselect_row.connect (slot (*this, &Editor::edit_group_unselected)); + + list stupid_list; + + stupid_list.push_back ("*"); + stupid_list.push_back (_("-all-")); + + edit_group_list.rows().push_back (stupid_list); + edit_group_list.rows().back().set_data (0); + edit_group_list.rows().back().select(); + + edit_group_vbox.pack_start (edit_group_list_button, false, false); + edit_group_vbox.pack_start (edit_group_list_scroller, true, true); + + route_list_frame.set_name ("BaseFrame"); + route_list_frame.set_shadow_type (GTK_SHADOW_IN); + route_list_frame.add (route_list_scroller); + + edit_group_list_frame.set_name ("BaseFrame"); + edit_group_list_frame.set_shadow_type (GTK_SHADOW_IN); + edit_group_list_frame.add (edit_group_vbox); + + route_group_vpane.add1 (route_list_frame); + route_group_vpane.add2 (edit_group_list_frame); + + list_vpacker.pack_start (route_group_vpane, true, true); + + region_list_hidden_node = region_list_display.rows().end(); + + region_list_display.add_events (GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK|GDK_POINTER_MOTION_MASK); + + region_list_display.drag_dest_set (GTK_DEST_DEFAULT_ALL, + target_table, n_targets - 1, + GdkDragAction (GDK_ACTION_COPY|GDK_ACTION_MOVE)); + region_list_display.drag_data_received.connect (slot (*this, &Editor::region_list_display_drag_data_received)); + + region_list_scroller.add (region_list_display); + region_list_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + region_list_display.set_name ("RegionListDisplay"); + region_list_display.set_usize (100, -1); + region_list_display.column_titles_active (); + region_list_display.set_selection_mode (GTK_SELECTION_SINGLE); + + region_list_display.set_data ("editor", this); + region_list_display.set_compare_func (_region_list_sorter); + region_list_sort_type = ByName; + reset_region_list_sort_type (region_list_sort_type); + + region_list_display.set_flags (GTK_CAN_FOCUS); + + region_list_display.key_press_event.connect (slot (*this, &Editor::region_list_display_key_press)); + region_list_display.key_release_event.connect (slot (*this, &Editor::region_list_display_key_release)); + region_list_display.button_press_event.connect (slot (*this, &Editor::region_list_display_button_press)); + region_list_display.button_release_event.connect (slot (*this, &Editor::region_list_display_button_release)); + region_list_display.motion_notify_event.connect (slot (*this, &Editor::region_list_display_motion)); + region_list_display.enter_notify_event.connect (slot (*this, &Editor::region_list_display_enter_notify)); + region_list_display.leave_notify_event.connect (slot (*this, &Editor::region_list_display_leave_notify)); + region_list_display.select_row.connect (slot (*this, &Editor::region_list_display_selected)); + region_list_display.unselect_row.connect (slot (*this, &Editor::region_list_display_unselected)); + region_list_display.click_column.connect (slot (*this, &Editor::region_list_column_click)); + + named_selection_scroller.add (named_selection_display); + named_selection_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + named_selection_display.set_name ("RegionListDisplay"); + named_selection_display.set_usize (100, -1); + named_selection_display.column_titles_active (); + named_selection_display.set_selection_mode (GTK_SELECTION_SINGLE); + + named_selection_display.button_press_event.connect (slot (*this, &Editor::named_selection_display_button_press)); + named_selection_display.select_row.connect (slot (*this, &Editor::named_selection_display_selected)); + named_selection_display.unselect_row.connect (slot (*this, &Editor::named_selection_display_unselected)); + + region_selection_vpane.pack1 (region_list_scroller, true, true); + region_selection_vpane.pack2 (named_selection_scroller, true, true); + + canvas_region_list_pane.pack1 (edit_frame, true, true); + canvas_region_list_pane.pack2 (region_selection_vpane, true, true); + + track_list_canvas_pane.size_allocate.connect_after (bind (slot (*this, &Editor::pane_allocation_handler), + static_cast (&track_list_canvas_pane))); + canvas_region_list_pane.size_allocate.connect_after (bind (slot (*this, &Editor::pane_allocation_handler), + static_cast (&canvas_region_list_pane))); + route_group_vpane.size_allocate.connect_after (bind (slot (*this, &Editor::pane_allocation_handler), + static_cast (&route_group_vpane))); + region_selection_vpane.size_allocate.connect_after (bind (slot (*this, &Editor::pane_allocation_handler), + static_cast (®ion_selection_vpane))); + + track_list_canvas_pane.pack1 (list_vpacker, true, true); + track_list_canvas_pane.pack2 (canvas_region_list_pane, true, true); + + /* provide special pane-handle event handling for easy "hide" action */ + + /* 0: collapse to show left/upper child + 1: collapse to show right/lower child + */ + + route_group_vpane.set_data ("collapse-direction", (gpointer) 0); + region_selection_vpane.set_data ("collapse-direction", (gpointer) 0); + canvas_region_list_pane.set_data ("collapse-direction", (gpointer) 0); + track_list_canvas_pane.set_data ("collapse-direction", (gpointer) 1); + + route_group_vpane.button_release_event.connect (bind (slot (pane_handler), static_cast (&route_group_vpane))); + region_selection_vpane.button_release_event.connect (bind (slot (pane_handler), static_cast (®ion_selection_vpane))); + canvas_region_list_pane.button_release_event.connect (bind (slot (pane_handler), static_cast (&canvas_region_list_pane))); + track_list_canvas_pane.button_release_event.connect (bind (slot (pane_handler), static_cast (&track_list_canvas_pane))); + + top_hbox.pack_start (toolbar_frame, true, true); + + HBox *hbox = manage (new HBox); + hbox->pack_start (track_list_canvas_pane, true, true); + + global_vpacker.pack_start (top_hbox, false, false); + global_vpacker.pack_start (*hbox, true, true); + + global_hpacker.pack_start (global_vpacker, true, true); + + set_name ("EditorWindow"); + + vpacker.pack_end (global_hpacker, true, true); + + _playlist_selector = new PlaylistSelector(); + _playlist_selector->delete_event.connect (bind (slot (just_hide_it), static_cast (_playlist_selector))); + + AudioRegionView::AudioRegionViewGoingAway.connect (slot (*this, &Editor::catch_vanishing_audio_regionview)); + + /* nudge stuff */ + + nudge_forward_button.add (*(manage (new Gtk::Pixmap (right_arrow_xpm)))); + nudge_backward_button.add (*(manage (new Gtk::Pixmap (left_arrow_xpm)))); + + ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards")); + ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards")); + + nudge_forward_button.set_name ("TransportButton"); + nudge_backward_button.set_name ("TransportButton"); + + fade_context_menu.set_name ("ArdourContextMenu"); + + install_keybindings (); + + set_title (_("ardour: editor")); + set_wmclass (_("ardour_editor"), "Ardour"); + + add (vpacker); + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK); + + configure_event.connect (slot (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler)); + delete_event.connect (slot (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close)); + + constructed = true; + instant_save (); +} + +Editor::~Editor() +{ + /* */ + if(image_socket_listener) + { + if(image_socket_listener->is_connected()) + { + image_socket_listener->close_connection() ; + } + + delete image_socket_listener ; + image_socket_listener = 0 ; + } + /* */ +} + +void +Editor::add_toplevel_controls (Container& cont) +{ + vpacker.pack_start (cont, false, false); + cont.show_all (); +} + +void +Editor::catch_vanishing_audio_regionview (AudioRegionView *rv) +{ + /* note: the selection will take care of the vanishing + audioregionview by itself. + */ + + if (clicked_regionview == rv) { + clicked_regionview = 0; + } + + if (entered_regionview == rv) { + set_entered_regionview (0); + } +} + +void +Editor::set_entered_regionview (AudioRegionView* rv) +{ + if (rv == entered_regionview) { + return; + } + + if (entered_regionview) { + entered_regionview->exited (); + } + + if ((entered_regionview = rv) != 0) { + entered_regionview->entered (); + } +} + +void +Editor::set_entered_track (TimeAxisView* tav) +{ + if (entered_track) { + entered_track->exited (); + } + + if ((entered_track = tav) != 0) { + entered_track->entered (); + } +} + +gint +Editor::left_track_canvas (GdkEventCrossing *ev) +{ + set_entered_track (0); + set_entered_regionview (0); + return FALSE; +} + + +void +Editor::initialize_canvas () +{ + gtk_canvas_init (); + + track_gtk_canvas = gtk_canvas_new_aa (); + + /* adjust sensitivity for "picking" items */ + + // GTK_CANVAS(track_gtk_canvas)->close_enough = 2; + + gtk_signal_connect (GTK_OBJECT(gtk_canvas_root (GTK_CANVAS(track_gtk_canvas))), "event", + (GtkSignalFunc) Editor::_track_canvas_event, this); + track_canvas = wrap (track_gtk_canvas); + track_canvas->set_name ("EditorMainCanvas"); + + track_canvas->add_events (GDK_POINTER_MOTION_HINT_MASK); + + track_canvas->leave_notify_event.connect (slot (*this, &Editor::left_track_canvas)); + + /* set up drag-n-drop */ + + track_canvas->drag_dest_set (GTK_DEST_DEFAULT_ALL, + target_table, n_targets - 1, + GdkDragAction (GDK_ACTION_COPY|GDK_ACTION_MOVE)); + track_canvas->drag_data_received.connect (slot (*this, &Editor::track_canvas_drag_data_received)); + + /* stuff for the verbose canvas cursor */ + + string fontname = get_font_for_style (N_("VerboseCanvasCursor")); + + verbose_canvas_cursor = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)), + gtk_canvas_text_get_type(), + "font", fontname.c_str(), + "anchor", GTK_ANCHOR_NW, + "fill_color_rgba", color_map[cVerboseCanvasCursor], + NULL); + verbose_cursor_visible = false; + + /* a group to hold time (measure) lines */ + + time_line_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)), + gtk_canvas_group_get_type(), + "x", 0.0, + "y", 0.0, + NULL); + + cursor_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)), + gtk_canvas_group_get_type(), + "x", 0.0, + "y", 0.0, + NULL); + + time_gtk_canvas = gtk_canvas_new_aa (); + time_canvas = wrap (time_gtk_canvas); + time_canvas->set_name ("EditorTimeCanvas"); + + time_canvas->add_events (GDK_POINTER_MOTION_HINT_MASK); + + meter_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(time_gtk_canvas)), + gtk_canvas_group_get_type(), + "x", 0.0, + "y", 0.0, + NULL); + tempo_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(time_gtk_canvas)), + gtk_canvas_group_get_type(), + "x", 0.0, + "y", timebar_height, + NULL); + marker_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(time_gtk_canvas)), + gtk_canvas_group_get_type(), + "x", 0.0, + "y", timebar_height * 2.0, + NULL); + range_marker_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(time_gtk_canvas)), + gtk_canvas_group_get_type(), + "x", 0.0, + "y", timebar_height * 3.0, + NULL); + transport_marker_group = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(time_gtk_canvas)), + gtk_canvas_group_get_type(), + "x", 0.0, + "y", timebar_height * 4.0, + NULL); + + tempo_bar = gtk_canvas_item_new (GTK_CANVAS_GROUP(tempo_group), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", max_canvas_coordinate, + "y2", timebar_height, + "fill_color_rgba", color_map[cTempoBar], + "outline_pixels", 0, + NULL); + meter_bar = gtk_canvas_item_new (GTK_CANVAS_GROUP(meter_group), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", max_canvas_coordinate, + "y2", timebar_height, + "fill_color_rgba", color_map[cMeterBar], + "outline_pixels", 0, + NULL); + marker_bar = gtk_canvas_item_new (GTK_CANVAS_GROUP(marker_group), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", max_canvas_coordinate, + "y2", timebar_height, + "fill_color_rgba", color_map[cMarkerBar], + "outline_pixels", 0, + NULL); + range_marker_bar = gtk_canvas_item_new (GTK_CANVAS_GROUP(range_marker_group), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", max_canvas_coordinate, + "y2", timebar_height, + "fill_color_rgba", color_map[cRangeMarkerBar], + "outline_pixels", 0, + NULL); + transport_marker_bar = gtk_canvas_item_new (GTK_CANVAS_GROUP(transport_marker_group), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", max_canvas_coordinate, + "y2", timebar_height, + "fill_color_rgba", color_map[cTransportMarkerBar], + "outline_pixels", 0, + NULL); + + range_bar_drag_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(range_marker_group), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 0.0, + "y2", timebar_height, + "fill_color_rgba", color_map[cRangeDragBarRectFill], + "outline_color_rgba", color_map[cRangeDragBarRect], + NULL); + gtk_canvas_item_hide (range_bar_drag_rect); + + transport_bar_drag_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(transport_marker_group), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 0.0, + "y2", timebar_height, + "fill_color_rgba", color_map[cTransportDragRectFill], + "outline_color_rgba", color_map[cTransportDragRect], + NULL); + gtk_canvas_item_hide (transport_bar_drag_rect); + + + marker_drag_line_points = gtk_canvas_points_new (2); + marker_drag_line_points->coords[0] = 0.0; + marker_drag_line_points->coords[1] = 0.0; + marker_drag_line_points->coords[2] = 0.0; + marker_drag_line_points->coords[3] = 0.0; + + + //cerr << "set mdl points, nc = " << marker_drag_line_points->num_points << endl; + marker_drag_line = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)), + gtk_canvas_line_get_type(), + "width_pixels", 1, + "fill_color_rgba", color_map[cMarkerDragLine], + "points", marker_drag_line_points, + NULL); + gtk_canvas_item_hide (marker_drag_line); + + range_marker_drag_rect = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 0.0, + "y2", 0.0, + "fill_color_rgba", color_map[cRangeDragRectFill], + "outline_color_rgba", color_map[cRangeDragRect], + NULL); + gtk_canvas_item_hide (range_marker_drag_rect); + + + transport_loop_range_rect = gtk_canvas_item_new ((GTK_CANVAS_GROUP(time_line_group)), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 0.0, + "y2", 0.0, + "fill_color_rgba", color_map[cTransportLoopRectFill], + "outline_color_rgba", color_map[cTransportLoopRect], + "outline_pixels", 1, + NULL); + gtk_canvas_item_hide (transport_loop_range_rect); + + transport_punch_range_rect = gtk_canvas_item_new ((GTK_CANVAS_GROUP(time_line_group)), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 0.0, + "y2", 0.0, + "fill_color_rgba", color_map[cTransportPunchRectFill], + "outline_color_rgba", color_map[cTransportPunchRect], + "outline_pixels", 0, + NULL); + gtk_canvas_item_lower_to_bottom (transport_punch_range_rect); + gtk_canvas_item_lower_to_bottom (transport_loop_range_rect); // loop on the bottom + gtk_canvas_item_hide (transport_punch_range_rect); + + transport_punchin_line = gtk_canvas_item_new ((GTK_CANVAS_GROUP(time_line_group)), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 0.0, + "y2", 0.0, + "outline_color_rgba", color_map[cPunchInLine], + "outline_pixels", 1, + NULL); + gtk_canvas_item_hide (transport_punchin_line); + + transport_punchout_line = gtk_canvas_item_new ((GTK_CANVAS_GROUP(time_line_group)), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 0.0, + "y2", 0.0, + "outline_color_rgba", color_map[cPunchOutLine], + "outline_pixels", 1, + NULL); + gtk_canvas_item_hide (transport_punchout_line); + + + + + // used to show zoom mode active zooming + zoom_rect = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 0.0, + "y2", 0.0, + "fill_color_rgba", color_map[cZoomRectFill], + "outline_color_rgba", color_map[cZoomRect], + "outline_pixels", 1, + NULL); + gtk_canvas_item_hide (zoom_rect); + gtk_signal_connect (GTK_OBJECT(zoom_rect), "event", + (GtkSignalFunc) PublicEditor::canvas_zoom_rect_event, + this); + + // used as rubberband rect + rubberband_rect = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 0.0, + "y2", 0.0, + "outline_color_rgba", color_map[cRubberBandRect], + "fill_color_rgba", (guint32) color_map[cRubberBandRectFill], + "outline_pixels", 1, + NULL); + gtk_canvas_item_hide (rubberband_rect); + + + + gtk_signal_connect (GTK_OBJECT(tempo_bar), "event", + (GtkSignalFunc) PublicEditor::canvas_tempo_bar_event, + this); + + gtk_signal_connect (GTK_OBJECT(meter_bar), "event", + (GtkSignalFunc) PublicEditor::canvas_meter_bar_event, + this); + + gtk_signal_connect (GTK_OBJECT(marker_bar), "event", + (GtkSignalFunc) PublicEditor::canvas_marker_bar_event, + this); + + gtk_signal_connect (GTK_OBJECT(range_marker_bar), "event", + (GtkSignalFunc) PublicEditor::canvas_range_marker_bar_event, + this); + + gtk_signal_connect (GTK_OBJECT(transport_marker_bar), "event", + (GtkSignalFunc) PublicEditor::canvas_transport_marker_bar_event, + this); + + /* separator lines */ + + tempo_line_points = gtk_canvas_points_new (2); + tempo_line_points->coords[0] = 0; + tempo_line_points->coords[1] = timebar_height; + tempo_line_points->coords[2] = max_canvas_coordinate; + tempo_line_points->coords[3] = timebar_height; + //cerr << "set tl points, nc = " << tempo_line_points->num_points << endl; + tempo_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(tempo_group), + gtk_canvas_line_get_type(), + "width_pixels", 0, + "fill_color", "black", + "points", tempo_line_points, + NULL); + + // cerr << "tempo line @ " << tempo_line << endl; + + meter_line_points = gtk_canvas_points_new (2); + meter_line_points->coords[0] = 0; + meter_line_points->coords[1] = timebar_height; + meter_line_points->coords[2] = max_canvas_coordinate; + meter_line_points->coords[3] = timebar_height; + // cerr << "set ml points, nc = " << tempo_line_points->num_points << endl; + meter_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(meter_group), + gtk_canvas_line_get_type(), + "width_pixels", 0, + "fill_color", "black", + "points", meter_line_points, + NULL); + + // cerr << "meter line @ " << tempo_line << endl; + + marker_line_points = gtk_canvas_points_new (2); + marker_line_points->coords[0] = 0; + marker_line_points->coords[1] = timebar_height; + marker_line_points->coords[2] = max_canvas_coordinate; + marker_line_points->coords[3] = timebar_height; + // cerr << "set ml2 points, nc = " << marker_line_points->num_points << endl; + marker_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(marker_group), + gtk_canvas_line_get_type(), + "width_pixels", 0, + "fill_color", "black", + "points", marker_line_points, + NULL); + // cerr << "set rml points, nc = " << marker_line_points->num_points << endl; + range_marker_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(range_marker_group), + gtk_canvas_line_get_type(), + "width_pixels", 0, + "fill_color", "black", + "points", marker_line_points, + NULL); + // cerr << "set tml2 points, nc = " << marker_line_points->num_points << endl; + transport_marker_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(transport_marker_group), + gtk_canvas_line_get_type(), + "width_pixels", 0, + "fill_color", "black", + "points", marker_line_points, + NULL); + + // cerr << "marker line @ " << marker_line << endl; + + ZoomChanged.connect (bind (slot (*this, &Editor::update_loop_range_view), false)); + ZoomChanged.connect (bind (slot (*this, &Editor::update_punch_range_view), false)); + + double time_height = timebar_height * 5; + double time_width = FLT_MAX/frames_per_unit; + gtk_canvas_set_scroll_region (GTK_CANVAS(time_gtk_canvas), 0.0, 0.0, time_width, time_height); + + edit_cursor = new Cursor (*this, "blue", (GtkSignalFunc) _canvas_edit_cursor_event); + playhead_cursor = new Cursor (*this, "red", (GtkSignalFunc) _canvas_playhead_cursor_event); + + track_canvas->size_allocate.connect (slot (*this, &Editor::track_canvas_allocate)); +} + +void +Editor::show_window () +{ + show_all (); + + /* now reset all audio_time_axis heights, because widgets might need + to be re-hidden + */ + + TimeAxisView *tv; + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + tv = (static_cast(*i)); + tv->reset_height (); + } +} + +void +Editor::tie_vertical_scrolling () +{ + edit_controls_scroller.get_vadjustment()->set_value (track_canvas_scroller.get_vadjustment()->get_value()); + + float y1 = track_canvas_scroller.get_vadjustment()->get_value(); + playhead_cursor->set_y_axis(y1); + edit_cursor->set_y_axis(y1); +} + +void +Editor::set_frames_per_unit (double fpu) +{ + jack_nframes_t frames; + + if (fpu == frames_per_unit) { + return; + } + + if (fpu < 1.0) { + fpu = 1.0; + } + + // convert fpu to frame count + + frames = (jack_nframes_t) (fpu * canvas_width); + + /* don't allow zooms that fit more than the maximum number + of frames into an 800 pixel wide space. + */ + + if (max_frames / fpu < 800.0) { + return; + } + + frames_per_unit = fpu; + + if (frames != zoom_range_clock.current_duration()) { + zoom_range_clock.set (frames); + } + + /* only update these if we not about to call reposition_x_origin, + which will do the same updates. + */ + + if (session) { + track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit); + } + + if (!no_zoom_repos_update) { + track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit); + update_hscroller (); + update_fixed_rulers (); + tempo_map_changed (Change (0)); + } + + if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) { + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + (*i)->reshow_selection (selection->time); + } + } + + ZoomChanged (); /* EMIT_SIGNAL */ + + if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame); + if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame); + + instant_save (); + +} + +void +Editor::instant_save () +{ + if (!constructed || !ARDOUR_UI::instance()->session_loaded) { + return; + } + + if (session) { + session->add_instant_xml(get_state(), session->path()); + } else { + Config->add_instant_xml(get_state(), Config->get_user_ardour_path()); + } +} + +void +Editor::reposition_x_origin (jack_nframes_t frame) +{ + if (frame != leftmost_frame) { + leftmost_frame = frame; + double pixel = frame_to_pixel (frame); + if (pixel >= track_canvas_scroller.get_hadjustment()->get_upper()) { + track_canvas_scroller.get_hadjustment()->set_upper (frame_to_pixel (frame + (current_page_frames()))); + } + track_canvas_scroller.get_hadjustment()->set_value (frame/frames_per_unit); + XOriginChanged (); /* EMIT_SIGNAL */ + } +} + +void +Editor::edit_cursor_clock_changed() +{ + if (edit_cursor->current_frame != edit_cursor_clock.current_time()) { + edit_cursor->set_position (edit_cursor_clock.current_time()); + } +} + + +void +Editor::zoom_adjustment_changed () +{ + if (session == 0 || no_zoom_repos_update) { + return; + } + + double fpu = (double) zoom_range_clock.current_duration() / (double) canvas_width; + + if (fpu < 1.0) { + fpu = 1.0; + zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width)); + } + else if (fpu > session->current_end_frame() / (double) canvas_width) { + fpu = session->current_end_frame() / (double) canvas_width; + zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width)); + } + + temporal_zoom (fpu); +} + +void +Editor::canvas_horizontally_scrolled () +{ + /* XXX note the potential loss of accuracy here caused by + adjustments being 32bit floats with only a 24 bit mantissa, + whereas jack_nframes_t is at least a 32 bit uint32_teger. + */ + + leftmost_frame = (jack_nframes_t) floor (track_canvas_scroller.get_hadjustment()->get_value() * frames_per_unit); + + update_hscroller (); + update_fixed_rulers (); + + if (!edit_hscroll_dragging) { + tempo_map_changed (Change (0)); + } else { + update_tempo_based_rulers(); + } +} + +void +Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu) +{ + if (!repos_zoom_queued) { + Main::idle.connect (bind (slot (*this, &Editor::deferred_reposition_and_zoom), frame, nfpu)); + repos_zoom_queued = true; + } +} + +gint +Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu) +{ + /* if we need to force an update to the hscroller stuff, + don't set no_zoom_repos_update. + */ + + no_zoom_repos_update = (frame != leftmost_frame); + + set_frames_per_unit (nfpu); + if (no_zoom_repos_update) { + reposition_x_origin (frame); + } + no_zoom_repos_update = false; + repos_zoom_queued = false; + + return FALSE; +} + +void +Editor::realize_impl () +{ + /* Even though we're not using acceleration, we want the + labels to show up. + */ + + track_context_menu.accelerate (*this->get_toplevel()); + track_region_context_menu.accelerate (*this->get_toplevel()); + + Window::realize_impl (); + + GdkPixmap* empty_pixmap = gdk_pixmap_new (get_window(), 1, 1, 1); + GdkPixmap* empty_bitmap = gdk_pixmap_new (get_window(), 1, 1, 1); + GdkColor white = { 0, 0, 0 }; + + null_cursor = gdk_cursor_new_from_pixmap (empty_pixmap, empty_bitmap, &white, &white, 0, 0); +} + +void +Editor::map__impl () +{ + Window::map__impl (); + + track_canvas_scroller.get_window().set_cursor (current_canvas_cursor); + time_canvas_scroller.get_window().set_cursor (timebar_cursor); +} + +void +Editor::track_canvas_allocate (GtkAllocation *alloc) +{ + canvas_width = alloc->width; + canvas_height = alloc->height; + + if (session == 0 && !ARDOUR_UI::instance()->will_create_new_session_automatically()) { + + string fontname = get_font_for_style (N_("FirstActionMessage")); + + const char *txt1 = _("Start a new session\n"); + const char *txt2 = _("via Session menu"); + + /* this mess of code is here to find out how wide this text is and + position the message in the center of the editor window. there + are two lines, so we use the longer of the the lines to + compute width, and multiply the height by 2. + */ + + gint width; + gint lbearing; + gint rbearing; + gint ascent; + gint descent; + + /* this is a dummy widget that exists so that we can get the + style from the RC file. + */ + + Label foo (_(txt2)); + foo.set_name ("NoSessionMessage"); + foo.ensure_style (); + + gdk_string_extents (foo.get_style()->get_font(), + _(txt2), + &lbearing, + &rbearing, + &width, + &ascent, + &descent); + + if (first_action_message == 0) { + + char txt[strlen(txt1)+strlen(txt2)+1]; + + /* merge both lines */ + + strcpy (txt, _(txt1)); + strcat (txt, _(txt2)); + + first_action_message = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(track_gtk_canvas)), + gtk_canvas_text_get_type(), + "font", fontname.c_str(), + "fill_color_rgba", color_map[cFirstActionMessage], + "x", (gdouble) (canvas_width - width) / 2.0, + "y", (gdouble) (canvas_height/2.0) - (2.0 * (ascent+descent)), + "anchor", GTK_ANCHOR_NORTH_WEST, + "text", txt, + NULL); + + } else { + + /* center it */ + + gtk_canvas_item_set (first_action_message, + "x", (gdouble) (canvas_width - width) / 2.0, + "y", (gdouble) (canvas_height/2.0) - (2.0 * (ascent+descent)), + NULL); + } + } + + zoom_range_clock.set ((jack_nframes_t) (canvas_width * frames_per_unit)); + edit_cursor->set_position (edit_cursor->current_frame); + playhead_cursor->set_position (playhead_cursor->current_frame); + reset_scrolling_region (alloc); + + Resized (); /* EMIT_SIGNAL */ +} + +void +Editor::reset_scrolling_region (GtkAllocation *alloc) +{ + guint32 last_canvas_unit; + double height; + guint32 canvas_alloc_height, canvas_alloc_width; + TrackViewList::iterator i; + static bool first_time = true; + + /* We need to make sure that the canvas always has its + scrolling region set to larger of: + + - the size allocated for it (within the container its packed in) + - the size required to see the entire session + + If we don't ensure at least the first of these, the canvas + does some wierd and in my view unnecessary stuff to center + itself within the allocated area, which causes bad, bad + results. + + XXX GnomeCanvas has fixed this, and has an option to + control the centering behaviour. + */ + + last_canvas_unit = (guint32) ceil ((float) max_frames / frames_per_unit); + + height = 0; + + if (session) { + for (i = track_views.begin(); i != track_views.end(); ++i) { + if ((*i)->control_parent) { + height += (*i)->effective_height; + height += track_spacing; + } + } + + if (height) { + height -= track_spacing; + } + } + + canvas_height = (guint32) height; + + if (alloc) { + canvas_alloc_height = alloc->height; + canvas_alloc_width = alloc->width; + } else { + canvas_alloc_height = track_gtk_canvas->allocation.height; + canvas_alloc_width = track_gtk_canvas->allocation.width; + } + + canvas_height = max (canvas_height, canvas_alloc_height); + + gtk_canvas_set_scroll_region (GTK_CANVAS(track_gtk_canvas), 0.0, 0.0, + max (last_canvas_unit, canvas_alloc_width), + canvas_height); + + if (edit_cursor) edit_cursor->set_length (canvas_alloc_height); + if (playhead_cursor) playhead_cursor->set_length (canvas_alloc_height); + + if (marker_drag_line) { + marker_drag_line_points->coords[3] = canvas_height; + // cerr << "set mlA points, nc = " << marker_drag_line_points->num_points << endl; + gtk_canvas_item_set (marker_drag_line, "points", marker_drag_line_points, NULL); + } + if (range_marker_drag_rect) { + gtk_canvas_item_set (range_marker_drag_rect, "y1", 0.0, "y2", (double) canvas_height, NULL); + } + if (transport_loop_range_rect) { + gtk_canvas_item_set (transport_loop_range_rect, "y1", 0.0, "y2", (double) canvas_height, NULL); + } + if (transport_punch_range_rect) { + gtk_canvas_item_set (transport_punch_range_rect, "y1", 0.0, "y2", (double) canvas_height, NULL); + } + if (transport_punchin_line) { + gtk_canvas_item_set (transport_punchin_line, "y1", 0.0, "y2", (double) canvas_height, NULL); + } + if (transport_punchout_line) { + gtk_canvas_item_set (transport_punchout_line, "y1", 0.0, "y2", (double) canvas_height, NULL); + } + + + update_fixed_rulers (); + + if (is_visible() && first_time) { + tempo_map_changed (Change (0)); + first_time = false; + } else { + redisplay_tempo (); + } +} + +void +Editor::queue_session_control_changed (Session::ControlType t) +{ + Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &Editor::session_control_changed), t)); +} + +void +Editor::session_control_changed (Session::ControlType t) +{ + // right now we're only tracking the loop and punch state + + switch (t) { + case Session::AutoLoop: + update_loop_range_view (true); + break; + case Session::PunchIn: + case Session::PunchOut: + update_punch_range_view (true); + break; + + default: + break; + } +} + +void +Editor::fake_add_edit_group (RouteGroup *group) +{ + Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &Editor::add_edit_group), group)); +} + +void +Editor::fake_handle_new_audio_region (AudioRegion *region) +{ + Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &Editor::handle_new_audio_region), region)); +} + +void +Editor::fake_handle_audio_region_removed (AudioRegion *region) +{ + Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &Editor::handle_audio_region_removed), region)); +} + +void +Editor::fake_handle_new_duration () +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &Editor::handle_new_duration)); +} + +void +Editor::start_scrolling () +{ + scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect + (slot (*this, &Editor::update_current_screen)); + + slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect + (slot (*this, &Editor::update_slower)); +} + +void +Editor::stop_scrolling () +{ + scroll_connection.disconnect (); + slower_update_connection.disconnect (); +} + +void +Editor::map_position_change (jack_nframes_t frame) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &Editor::map_position_change), frame)); + + if (session == 0 || !_follow_playhead) { + return; + } + + center_screen (frame); + playhead_cursor->set_position (frame); +} + +void +Editor::center_screen (jack_nframes_t frame) +{ + float page = canvas_width * frames_per_unit; + + /* if we're off the page, then scroll. + */ + + if (frame < leftmost_frame || frame >= leftmost_frame + page) { + center_screen_internal (frame,page); + } +} + +void +Editor::center_screen_internal (jack_nframes_t frame, float page) +{ + page /= 2; + + if (frame > page) { + frame -= (jack_nframes_t) page; + } else { + frame = 0; + } + + reposition_x_origin (frame); +} + +void +Editor::handle_new_duration () +{ + reset_scrolling_region (); + + if (session) { + track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit); + track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit); + } + + update_hscroller (); +} + +void +Editor::update_title_s (string snap_name) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Editor::update_title_s), snap_name)); + + update_title (); +} + +void +Editor::update_title () +{ + ENSURE_GUI_THREAD (slot (*this, &Editor::update_title)); + + if (session) { + bool dirty = session->dirty(); + + string wintitle = _("ardour: editor: "); + + if (dirty) { + wintitle += '['; + } + + wintitle += session->name(); + + if (session->snap_name() != session->name()) { + wintitle += ':'; + wintitle += session->snap_name(); + } + + if (dirty) { + wintitle += ']'; + } + + set_title (wintitle); + } +} + +void +Editor::connect_to_session (Session *t) +{ + session = t; + + if (first_action_message) { + gtk_canvas_item_hide (first_action_message); + } + + flush_track_canvas(); + + update_title (); + + session->going_away.connect (slot (*this, &Editor::session_going_away)); + + /* These signals can all be emitted by a non-GUI thread. Therefore the + handlers for them must not attempt to directly interact with the GUI, + but use Gtkmmext::UI::instance()->call_slot(); + */ + + session_connections.push_back (session->TransportStateChange.connect (slot (*this, &Editor::map_transport_state))); + session_connections.push_back (session->PositionChanged.connect (slot (*this, &Editor::map_position_change))); + session_connections.push_back (session->RouteAdded.connect (slot (*this, &Editor::handle_new_route_p))); + session_connections.push_back (session->AudioRegionAdded.connect (slot (*this, &Editor::fake_handle_new_audio_region))); + session_connections.push_back (session->AudioRegionRemoved.connect (slot (*this, &Editor::fake_handle_audio_region_removed))); + session_connections.push_back (session->DurationChanged.connect (slot (*this, &Editor::fake_handle_new_duration))); + session_connections.push_back (session->edit_group_added.connect (slot (*this, &Editor::fake_add_edit_group))); + session_connections.push_back (session->NamedSelectionAdded.connect (slot (*this, &Editor::handle_new_named_selection))); + session_connections.push_back (session->NamedSelectionRemoved.connect (slot (*this, &Editor::handle_new_named_selection))); + session_connections.push_back (session->DirtyChanged.connect (slot (*this, &Editor::update_title))); + session_connections.push_back (session->StateSaved.connect (slot (*this, &Editor::update_title_s))); + session_connections.push_back (session->AskAboutPlaylistDeletion.connect (slot (*this, &Editor::playlist_deletion_dialog))); + session_connections.push_back (session->RegionHiddenChange.connect (slot (*this, &Editor::region_hidden))); + + session_connections.push_back (session->SMPTEOffsetChanged.connect (slot (*this, &Editor::update_just_smpte))); + session_connections.push_back (session->SMPTETypeChanged.connect (slot (*this, &Editor::update_just_smpte))); + + session_connections.push_back (session->tempo_map().StateChanged.connect (slot (*this, &Editor::tempo_map_changed))); + + session->foreach_edit_group(this, &Editor::add_edit_group); + + editor_mixer_button.toggled.connect (slot (*this, &Editor::editor_mixer_button_toggled)); + editor_mixer_button.set_name (X_("EditorMixerButton")); + + edit_cursor_clock.set_session (session); + selection_start_clock.set_session (session); + selection_end_clock.set_session (session); + zoom_range_clock.set_session (session); + _playlist_selector->set_session (session); + nudge_clock.set_session (session); + + switch (session->get_edit_mode()) { + case Splice: + edit_mode_selector.get_entry()->set_text (edit_mode_strings[splice_index]); + break; + + case Slide: + edit_mode_selector.get_entry()->set_text (edit_mode_strings[slide_index]); + break; + } + + Location* loc = session->locations()->auto_loop_location(); + if (loc == 0) { + loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden)); + if (loc->start() == loc->end()) { + loc->set_end (loc->start() + 1); + } + session->locations()->add (loc, false); + session->set_auto_loop_location (loc); + } + else { + // force name + loc->set_name (_("Loop")); + } + + loc = session->locations()->auto_punch_location(); + if (loc == 0) { + loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden)); + if (loc->start() == loc->end()) { + loc->set_end (loc->start() + 1); + } + session->locations()->add (loc, false); + session->set_auto_punch_location (loc); + } + else { + // force name + loc->set_name (_("Punch")); + } + + update_loop_range_view (true); + update_punch_range_view (true); + + session->ControlChanged.connect (slot (*this, &Editor::queue_session_control_changed)); + + + refresh_location_display (); + session->locations()->added.connect (slot (*this, &Editor::add_new_location)); + session->locations()->removed.connect (slot (*this, &Editor::location_gone)); + session->locations()->changed.connect (slot (*this, &Editor::refresh_location_display)); + session->locations()->StateChanged.connect (slot (*this, &Editor::refresh_location_display_s)); + session->locations()->end_location()->changed.connect (slot (*this, &Editor::end_location_changed)); + + reset_scrolling_region (); + + redisplay_regions (); + redisplay_named_selections (); + + route_list.freeze (); + route_list.clear (); + session->foreach_route (this, &Editor::handle_new_route); + // route_list.select_all (); + route_list.sort (); + route_list_reordered (); + route_list.thaw (); + + if (embed_audio_item) { + embed_audio_item->set_sensitive (true); + } + if (import_audio_item) { + import_audio_item->set_sensitive (true); + } + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + (static_cast(*i))->set_samples_per_unit (frames_per_unit); + } + + /* ::reposition_x_origin() doesn't work right here, since the old + position may be zero already, and it does nothing in such + circumstances. + */ + + leftmost_frame = 0; + + track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit); + track_canvas_scroller.get_hadjustment()->set_value (0); + + update_hscroller (); + restore_ruler_visibility (); + tempo_map_changed (Change (0)); + + edit_cursor->set_position (0); + playhead_cursor->set_position (0); + + start_scrolling (); + + XMLNode* node = ARDOUR_UI::instance()->editor_settings(); + set_state (*node); + + /* don't show master bus in a new session */ + + if (ARDOUR_UI::instance()->session_is_new ()) { + + Gtk::CList_Helpers::RowList::iterator i; + Gtk::CList_Helpers::RowList& rowlist = route_list.rows(); + + route_list.freeze (); + + for (i = rowlist.begin(); i != rowlist.end(); ++i) { + TimeAxisView *tv = (TimeAxisView *) i->get_data (); + AudioTimeAxisView *atv; + + if ((atv = dynamic_cast(tv)) != 0) { + if (atv->route().master()) { + (*i)->unselect (); + } + } + } + + route_list.thaw (); + } +} + +void +Editor::build_cursors () +{ + GdkPixmap *source, *mask; + GdkColor fg = { 0, 65535, 0, 0 }; /* Red. */ + GdkColor bg = { 0, 0, 0, 65535 }; /* Blue. */ + + source = gdk_bitmap_create_from_data (NULL, hand_bits, + hand_width, hand_height); + mask = gdk_bitmap_create_from_data (NULL, handmask_bits, + handmask_width, handmask_height); + grabber_cursor = gdk_cursor_new_from_pixmap (source, mask, &fg, &bg, hand_x_hot, hand_y_hot); + gdk_pixmap_unref (source); + gdk_pixmap_unref (mask); + + + GdkColor mbg = { 0, 0, 0, 0 }; /* Black */ + GdkColor mfg = { 0, 0, 0, 65535 }; /* Blue. */ + + source = gdk_bitmap_create_from_data (NULL, mag_bits, + mag_width, mag_height); + mask = gdk_bitmap_create_from_data (NULL, magmask_bits, + mag_width, mag_height); + zoom_cursor = gdk_cursor_new_from_pixmap (source, mask, &mfg, &mbg, mag_x_hot, mag_y_hot); + gdk_pixmap_unref (source); + gdk_pixmap_unref (mask); + + GdkColor fbg = { 0, 65535, 65535, 65535 }; + GdkColor ffg = { 0, 0, 0, 0 }; + + source = gdk_bitmap_create_from_data (NULL, fader_cursor_bits, + fader_cursor_width, fader_cursor_height); + mask = gdk_bitmap_create_from_data (NULL, fader_cursor_mask_bits, + fader_cursor_width, fader_cursor_height); + fader_cursor = gdk_cursor_new_from_pixmap (source, mask, &ffg, &fbg, fader_cursor_x_hot, fader_cursor_y_hot); + gdk_pixmap_unref (source); + gdk_pixmap_unref (mask); + + source = gdk_bitmap_create_from_data (NULL, speaker_cursor_bits, + speaker_cursor_width, speaker_cursor_height); + mask = gdk_bitmap_create_from_data (NULL, speaker_cursor_mask_bits, + speaker_cursor_width, speaker_cursor_height); + speaker_cursor = gdk_cursor_new_from_pixmap (source, mask, &ffg, &fbg, speaker_cursor_x_hot, speaker_cursor_y_hot); + gdk_pixmap_unref (source); + gdk_pixmap_unref (mask); + + cross_hair_cursor = gdk_cursor_new (GDK_CROSSHAIR); + trimmer_cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW); + selector_cursor = gdk_cursor_new (GDK_XTERM); + time_fx_cursor = gdk_cursor_new (GDK_SIZING); + wait_cursor = gdk_cursor_new (GDK_WATCH); + timebar_cursor = gdk_cursor_new (GDK_LEFT_PTR); +} + +void +Editor::popup_fade_context_menu (int button, int32_t time, GtkCanvasItem* item, ItemType item_type) +{ + using namespace Menu_Helpers; + AudioRegionView* arv = static_cast (gtk_object_get_data (GTK_OBJECT(item), "regionview")); + + if (arv == 0) { + fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg; + /*NOTREACHED*/ + } + + MenuList& items (fade_context_menu.items()); + + items.clear (); + + switch (item_type) { + case FadeInItem: + case FadeInHandleItem: + if (arv->region.fade_in_active()) { + items.push_back (MenuElem (_("Deactivate"), bind (slot (*arv, &AudioRegionView::set_fade_in_active), false))); + } else { + items.push_back (MenuElem (_("Activate"), bind (slot (*arv, &AudioRegionView::set_fade_in_active), true))); + } + + items.push_back (SeparatorElem()); + + items.push_back (MenuElem (_("Linear"), bind (slot (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear))); + items.push_back (MenuElem (_("Slowest"), bind (slot (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB))); + items.push_back (MenuElem (_("Slow"), bind (slot (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast))); + items.push_back (MenuElem (_("Fast"), bind (slot (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA))); + items.push_back (MenuElem (_("Fastest"), bind (slot (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow))); + break; + + case FadeOutItem: + case FadeOutHandleItem: + if (arv->region.fade_out_active()) { + items.push_back (MenuElem (_("Deactivate"), bind (slot (*arv, &AudioRegionView::set_fade_out_active), false))); + } else { + items.push_back (MenuElem (_("Activate"), bind (slot (*arv, &AudioRegionView::set_fade_out_active), true))); + } + + items.push_back (SeparatorElem()); + + items.push_back (MenuElem (_("Linear"), bind (slot (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear))); + items.push_back (MenuElem (_("Slowest"), bind (slot (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast))); + items.push_back (MenuElem (_("Slow"), bind (slot (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB))); + items.push_back (MenuElem (_("Fast"), bind (slot (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA))); + items.push_back (MenuElem (_("Fastest"), bind (slot (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow))); + + break; + default: + fatal << _("programming error: ") + << X_("non-fade canvas item passed to popup_fade_context_menu()") + << endmsg; + /*NOTREACHED*/ + } + + fade_context_menu.popup (button, time); +} + +void +Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame) +{ + using namespace Menu_Helpers; + Menu* (Editor::*build_menu_function)(jack_nframes_t); + Menu *menu; + + switch (item_type) { + case RegionItem: + case AudioRegionViewName: + case AudioRegionViewNameHighlight: + if (with_selection) { + build_menu_function = &Editor::build_track_selection_context_menu; + } else { + build_menu_function = &Editor::build_track_region_context_menu; + } + break; + + case SelectionItem: + if (with_selection) { + build_menu_function = &Editor::build_track_selection_context_menu; + } else { + build_menu_function = &Editor::build_track_context_menu; + } + break; + + case CrossfadeViewItem: + build_menu_function = &Editor::build_track_crossfade_context_menu; + break; + + case StreamItem: + if (clicked_audio_trackview->get_diskstream()) { + build_menu_function = &Editor::build_track_context_menu; + } else { + build_menu_function = &Editor::build_track_bus_context_menu; + } + break; + + default: + /* probably shouldn't happen but if it does, we don't care */ + return; + } + + menu = (this->*build_menu_function)(frame); + menu->set_name ("ArdourContextMenu"); + + /* now handle specific situations */ + + switch (item_type) { + case RegionItem: + case AudioRegionViewName: + case AudioRegionViewNameHighlight: + if (!with_selection) { + if (region_edit_menu_split_item) { + if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) { + region_edit_menu_split_item->set_sensitive (true); + } else { + region_edit_menu_split_item->set_sensitive (false); + } + } + if (region_edit_menu_split_multichannel_item) { + if (clicked_regionview && clicked_regionview->region.n_channels() > 1) { + region_edit_menu_split_multichannel_item->set_sensitive (true); + } else { + region_edit_menu_split_multichannel_item->set_sensitive (false); + } + } + } + break; + + case SelectionItem: + break; + + case CrossfadeViewItem: + break; + + case StreamItem: + break; + + default: + /* probably shouldn't happen but if it does, we don't care */ + return; + } + + if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) { + + /* Bounce to disk */ + + using namespace Menu_Helpers; + MenuList& edit_items = menu->items(); + + edit_items.push_back (SeparatorElem()); + + switch (clicked_audio_trackview->audio_track()->freeze_state()) { + case AudioTrack::NoFreeze: + edit_items.push_back (MenuElem (_("Freeze"), slot (*this, &Editor::freeze_route))); + break; + + case AudioTrack::Frozen: + edit_items.push_back (MenuElem (_("Unfreeze"), slot (*this, &Editor::unfreeze_route))); + break; + + case AudioTrack::UnFrozen: + edit_items.push_back (MenuElem (_("Freeze"), slot (*this, &Editor::freeze_route))); + break; + } + + } + + menu->popup (button, time); +} + +Menu* +Editor::build_track_context_menu (jack_nframes_t ignored) +{ + using namespace Menu_Helpers; + + MenuList& edit_items = track_context_menu.items(); + edit_items.clear(); + + add_dstream_context_items (edit_items); + return &track_context_menu; +} + +Menu* +Editor::build_track_bus_context_menu (jack_nframes_t ignored) +{ + using namespace Menu_Helpers; + + MenuList& edit_items = track_context_menu.items(); + edit_items.clear(); + + add_bus_context_items (edit_items); + return &track_context_menu; +} + +Menu* +Editor::build_track_region_context_menu (jack_nframes_t frame) +{ + using namespace Menu_Helpers; + MenuList& edit_items = track_region_context_menu.items(); + edit_items.clear(); + + AudioTimeAxisView* atv = dynamic_cast (clicked_trackview); + + if (atv) { + DiskStream* ds; + Playlist* pl; + + if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) { + Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed())); + for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { + add_region_context_items (atv->view, (*i), edit_items); + } + delete regions; + } + } + + add_dstream_context_items (edit_items); + + return &track_region_context_menu; +} + +Menu* +Editor::build_track_crossfade_context_menu (jack_nframes_t frame) +{ + using namespace Menu_Helpers; + MenuList& edit_items = track_crossfade_context_menu.items(); + edit_items.clear (); + + AudioTimeAxisView* atv = dynamic_cast (clicked_trackview); + + if (atv) { + DiskStream* ds; + Playlist* pl; + AudioPlaylist* apl; + + if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast (pl)) != 0)) { + + Playlist::RegionList* regions = pl->regions_at (frame); + AudioPlaylist::Crossfades xfades; + + apl->crossfades_at (frame, xfades); + + bool many = xfades.size() > 1; + + for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) { + add_crossfade_context_items (atv->view, (*i), edit_items, many); + } + + for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) { + add_region_context_items (atv->view, (*i), edit_items); + } + + delete regions; + } + } + + add_dstream_context_items (edit_items); + + return &track_crossfade_context_menu; +} + +Menu* +Editor::build_track_selection_context_menu (jack_nframes_t ignored) +{ + using namespace Menu_Helpers; + MenuList& edit_items = track_selection_context_menu.items(); + edit_items.clear (); + + add_selection_context_items (edit_items); + add_dstream_context_items (edit_items); + + return &track_selection_context_menu; +} + +void +Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many) +{ + using namespace Menu_Helpers; + Menu *xfade_menu = manage (new Menu); + MenuList& items = xfade_menu->items(); + xfade_menu->set_name ("ArdourContextMenu"); + string str; + + if (xfade->active()) { + str = _("Mute"); + } else { + str = _("Unmute"); + } + + items.push_back (MenuElem (str, bind (slot (*this, &Editor::toggle_xfade_active), xfade))); + items.push_back (MenuElem (_("Edit"), bind (slot (*this, &Editor::edit_xfade), xfade))); + + if (xfade->can_follow_overlap()) { + + if (xfade->following_overlap()) { + str = _("Convert to short"); + } else { + str = _("Convert to full"); + } + + items.push_back (MenuElem (str, bind (slot (*this, &Editor::toggle_xfade_length), xfade))); + } + + if (many) { + str = xfade->out().name(); + str += "->"; + str += xfade->in().name(); + } else { + str = _("Crossfade"); + } + + edit_items.push_back (MenuElem (str, *xfade_menu)); + edit_items.push_back (SeparatorElem()); +} + +void +Editor::xfade_edit_left_region () +{ + if (clicked_crossfadeview) { + clicked_crossfadeview->left_view.show_region_editor (); + } +} + +void +Editor::xfade_edit_right_region () +{ + if (clicked_crossfadeview) { + clicked_crossfadeview->right_view.show_region_editor (); + } +} + +void +Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items) +{ + using namespace Menu_Helpers; + Menu *region_menu = manage (new Menu); + MenuList& items = region_menu->items(); + region_menu->set_name ("ArdourContextMenu"); + + AudioRegion* ar = 0; + + if (region) { + ar = dynamic_cast (region); + } + + /* when this particular menu pops up, make the relevant region + become selected. + */ + + region_menu->map_event.connect (bind (slot (*this, &Editor::set_selected_regionview_from_map_event), sv, region)); + + items.push_back (MenuElem (_("Popup region editor"), slot (*this, &Editor::edit_region))); + items.push_back (MenuElem (_("Raise to top layer"), slot (*this, &Editor::raise_region_to_top))); + items.push_back (MenuElem (_("Lower to bottom layer"), slot (*this, &Editor::lower_region_to_bottom))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Define sync point"), slot (*this, &Editor::set_region_sync_from_edit_cursor))); + items.push_back (MenuElem (_("Remove sync point"), slot (*this, &Editor::remove_region_sync))); + items.push_back (SeparatorElem()); + + items.push_back (MenuElem (_("Audition"), slot (*this, &Editor::audition_selected_region))); + items.push_back (MenuElem (_("Export"), slot (*this, &Editor::export_region))); + items.push_back (MenuElem (_("Bounce"), slot (*this, &Editor::bounce_region_selection))); + items.push_back (SeparatorElem()); + + /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler + might be able to figure out which overloaded member function to use in + a bind() call ... + */ + + void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op; + + items.push_back (MenuElem (_("Lock"), bind (slot (*this, type_A_pmf), &Region::set_locked, true))); + items.push_back (MenuElem (_("Unlock"), bind (slot (*this, type_A_pmf), &Region::set_locked, false))); + items.push_back (SeparatorElem()); + + if (region->muted()) { + items.push_back (MenuElem (_("Unmute"), bind (slot (*this, type_A_pmf), &Region::set_muted, false))); + } else { + items.push_back (MenuElem (_("Mute"), bind (slot (*this, type_A_pmf), &Region::set_muted, true))); + } + items.push_back (SeparatorElem()); + + items.push_back (MenuElem (_("Original position"), slot (*this, &Editor::naturalize))); + items.push_back (SeparatorElem()); + + + if (ar) { + + items.push_back (MenuElem (_("Toggle envelope visibility"), slot (*this, &Editor::toggle_gain_envelope_visibility))); + items.push_back (MenuElem (_("Toggle envelope active"), slot (*this, &Editor::toggle_gain_envelope_active))); + items.push_back (SeparatorElem()); + + if (ar->scale_amplitude() != 1.0f) { + items.push_back (MenuElem (_("DeNormalize"), slot (*this, &Editor::denormalize_region))); + } else { + items.push_back (MenuElem (_("Normalize"), slot (*this, &Editor::normalize_region))); + } + } + items.push_back (MenuElem (_("Reverse"), slot (*this, &Editor::reverse_region))); + items.push_back (SeparatorElem()); + + /* Nudge region */ + + Menu *nudge_menu = manage (new Menu()); + MenuList& nudge_items = nudge_menu->items(); + nudge_menu->set_name ("ArdourContextMenu"); + + nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (slot (*this, &Editor::nudge_forward), false)))); + nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (slot (*this, &Editor::nudge_backward), false)))); + nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (slot (*this, &Editor::nudge_forward_capture_offset)))); + nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (slot (*this, &Editor::nudge_backward_capture_offset)))); + + items.push_back (MenuElem (_("Nudge"), *nudge_menu)); + items.push_back (SeparatorElem()); + + Menu *trim_menu = manage (new Menu); + MenuList& trim_items = trim_menu->items(); + trim_menu->set_name ("ArdourContextMenu"); + + trim_items.push_back (MenuElem (_("Start to edit cursor"), slot (*this, &Editor::trim_region_from_edit_cursor))); + trim_items.push_back (MenuElem (_("Edit cursor to end"), slot (*this, &Editor::trim_region_to_edit_cursor))); + + items.push_back (MenuElem (_("Trim"), *trim_menu)); + items.push_back (SeparatorElem()); + + items.push_back (MenuElem (_("Split"), (slot (*this, &Editor::split_region)))); + region_edit_menu_split_item = items.back(); + + items.push_back (MenuElem (_("Make mono regions"), (slot (*this, &Editor::split_multichannel_region)))); + region_edit_menu_split_multichannel_item = items.back(); + + items.push_back (MenuElem (_("Duplicate"), (bind (slot (*this, &Editor::duplicate_dialog), true)))); + items.push_back (MenuElem (_("Fill Track"), (slot (*this, &Editor::region_fill_track)))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Remove"), slot (*this, &Editor::remove_clicked_region))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Destroy"), slot (*this, &Editor::destroy_clicked_region))); + + /* OK, stick the region submenu at the top of the list, and then add + the standard items. + */ + + /* we have to hack up the region name because "_" has a special + meaning for menu titles. + */ + + string::size_type pos = 0; + string menu_item_name = region->name(); + + while ((pos = menu_item_name.find ("_", pos)) != string::npos) { + menu_item_name.replace (pos, 1, "__"); + pos += 2; + } + + edit_items.push_back (MenuElem (menu_item_name, *region_menu)); + edit_items.push_back (SeparatorElem()); +} + +void +Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items) +{ + using namespace Menu_Helpers; + Menu *selection_menu = manage (new Menu); + MenuList& items = selection_menu->items(); + selection_menu->set_name ("ArdourContextMenu"); + + items.push_back (MenuElem (_("Play range"), slot (*this, &Editor::play_selection))); + items.push_back (MenuElem (_("Loop range"), slot (*this, &Editor::set_route_loop_selection))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Create chunk from range"), slot (*this, &Editor::name_selection))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Create Region"), slot (*this, &Editor::new_region_from_selection))); + items.push_back (MenuElem (_("Separate Region"), slot (*this, &Editor::separate_region_from_selection))); + items.push_back (MenuElem (_("Crop Region to range"), slot (*this, &Editor::crop_region_to_selection))); + items.push_back (MenuElem (_("Bounce range"), slot (*this, &Editor::bounce_range_selection))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Duplicate"), bind (slot (*this, &Editor::duplicate_dialog), false))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Export"), slot (*this, &Editor::export_selection))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Fill range w/Region"), slot (*this, &Editor::region_fill_selection))); + + edit_items.push_back (MenuElem (_("Range"), *selection_menu)); + edit_items.push_back (SeparatorElem()); +} + +void +Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items) +{ + using namespace Menu_Helpers; + + /* Playback */ + + Menu *play_menu = manage (new Menu); + MenuList& play_items = play_menu->items(); + play_menu->set_name ("ArdourContextMenu"); + + play_items.push_back (MenuElem (_("Play from edit cursor"))); + play_items.push_back (MenuElem (_("Play from start"), slot (*this, &Editor::play_from_start))); + play_items.push_back (MenuElem (_("Play region"), slot (*this, &Editor::play_selected_region))); + play_items.push_back (SeparatorElem()); + play_items.push_back (MenuElem (_("Loop Region"), slot (*this, &Editor::loop_selected_region))); + + edit_items.push_back (MenuElem (_("Play"), *play_menu)); + + /* Selection */ + + Menu *select_menu = manage (new Menu); + MenuList& select_items = select_menu->items(); + select_menu->set_name ("ArdourContextMenu"); + + select_items.push_back (MenuElem (_("Select All in track"), bind (slot (*this, &Editor::select_all_in_track), false))); + select_items.push_back (MenuElem (_("Select All"), bind (slot (*this, &Editor::select_all), false))); + select_items.push_back (MenuElem (_("Invert in track"), slot (*this, &Editor::invert_selection_in_track))); + select_items.push_back (MenuElem (_("Invert"), slot (*this, &Editor::invert_selection))); + select_items.push_back (SeparatorElem()); + select_items.push_back (MenuElem (_("Select loop range"), slot (*this, &Editor::set_selection_from_loop))); + select_items.push_back (MenuElem (_("Select punch range"), slot (*this, &Editor::set_selection_from_punch))); + select_items.push_back (SeparatorElem()); + + edit_items.push_back (MenuElem (_("Select"), *select_menu)); + + /* Cut-n-Paste */ + + Menu *cutnpaste_menu = manage (new Menu); + MenuList& cutnpaste_items = cutnpaste_menu->items(); + cutnpaste_menu->set_name ("ArdourContextMenu"); + + cutnpaste_items.push_back (MenuElem (_("Cut"), slot (*this, &Editor::cut))); + cutnpaste_items.push_back (MenuElem (_("Copy"), slot (*this, &Editor::copy))); + cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (slot (*this, &Editor::paste), 1.0f))); + cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), slot (*this, &Editor::mouse_paste))); + + cutnpaste_items.push_back (SeparatorElem()); + + cutnpaste_items.push_back (MenuElem (_("Align"), bind (slot (*this, &Editor::align), ARDOUR::SyncPoint))); + cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (slot (*this, &Editor::align_relative), ARDOUR::SyncPoint))); + + cutnpaste_items.push_back (SeparatorElem()); + + cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (slot (*this, &Editor::paste_named_selection), 1.0f))); + + cutnpaste_items.push_back (SeparatorElem()); + + cutnpaste_items.push_back (MenuElem (_("New Region from range"), slot (*this, &Editor::new_region_from_selection))); + cutnpaste_items.push_back (MenuElem (_("Separate Range"), slot (*this, &Editor::separate_region_from_selection))); + + edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu)); + + /* Adding new material */ + + Menu *import_menu = manage (new Menu()); + MenuList& import_items = import_menu->items(); + import_menu->set_name ("ArdourContextMenu"); + + import_items.push_back (MenuElem (_("Insert Region"), bind (slot (*this, &Editor::insert_region_list_selection), 1.0f))); + import_items.push_back (MenuElem (_("Insert external sndfile"), bind (slot (*this, &Editor::insert_sndfile), false))); + + edit_items.push_back (MenuElem (_("Import"), *import_menu)); + + /* Nudge track */ + + Menu *nudge_menu = manage (new Menu()); + MenuList& nudge_items = nudge_menu->items(); + nudge_menu->set_name ("ArdourContextMenu"); + + edit_items.push_back (SeparatorElem()); + nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (slot (*this, &Editor::nudge_track), false, true)))); + nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (slot (*this, &Editor::nudge_track), true, true)))); + nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (slot (*this, &Editor::nudge_track), false, false)))); + nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (slot (*this, &Editor::nudge_track), true, false)))); + + edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu)); +} + +void +Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items) +{ + using namespace Menu_Helpers; + + /* Playback */ + + Menu *play_menu = manage (new Menu); + MenuList& play_items = play_menu->items(); + play_menu->set_name ("ArdourContextMenu"); + + play_items.push_back (MenuElem (_("Play from edit cursor"))); + play_items.push_back (MenuElem (_("Play from start"), slot (*this, &Editor::play_from_start))); + edit_items.push_back (MenuElem (_("Play"), *play_menu)); + + /* Selection */ + + Menu *select_menu = manage (new Menu); + MenuList& select_items = select_menu->items(); + select_menu->set_name ("ArdourContextMenu"); + + select_items.push_back (MenuElem (_("Select All in track"), bind (slot (*this, &Editor::select_all_in_track), false))); + select_items.push_back (MenuElem (_("Select All"), bind (slot (*this, &Editor::select_all), false))); + select_items.push_back (MenuElem (_("Invert in track"), slot (*this, &Editor::invert_selection_in_track))); + select_items.push_back (MenuElem (_("Invert"), slot (*this, &Editor::invert_selection))); + select_items.push_back (SeparatorElem()); + select_items.push_back (MenuElem (_("Select loop range"), slot (*this, &Editor::set_selection_from_loop))); + select_items.push_back (MenuElem (_("Select punch range"), slot (*this, &Editor::set_selection_from_punch))); + select_items.push_back (SeparatorElem()); + + edit_items.push_back (MenuElem (_("Select"), *select_menu)); + + /* Cut-n-Paste */ + + Menu *cutnpaste_menu = manage (new Menu); + MenuList& cutnpaste_items = cutnpaste_menu->items(); + cutnpaste_menu->set_name ("ArdourContextMenu"); + + cutnpaste_items.push_back (MenuElem (_("Cut"), slot (*this, &Editor::cut))); + cutnpaste_items.push_back (MenuElem (_("Copy"), slot (*this, &Editor::copy))); + cutnpaste_items.push_back (MenuElem (_("Paste"), bind (slot (*this, &Editor::paste), 1.0f))); + + Menu *nudge_menu = manage (new Menu()); + MenuList& nudge_items = nudge_menu->items(); + nudge_menu->set_name ("ArdourContextMenu"); + + edit_items.push_back (SeparatorElem()); + nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (slot (*this, &Editor::nudge_track), false, true)))); + nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (slot (*this, &Editor::nudge_track), true, true)))); + nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (slot (*this, &Editor::nudge_track), false, false)))); + nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (slot (*this, &Editor::nudge_track), true, false)))); + + edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu)); +} + +/* CURSOR SETTING AND MARKS AND STUFF */ + +void +Editor::set_snap_to (SnapType st) +{ + snap_type = st; + vector txt = internationalize (snap_type_strings); + snap_type_selector.get_entry()->set_text (txt[(int)st]); + + instant_save (); + + switch (snap_type) { + case SnapToAThirtysecondBeat: + case SnapToASixteenthBeat: + case SnapToAEighthBeat: + case SnapToAQuarterBeat: + case SnapToAThirdBeat: + update_tempo_based_rulers (); + default: + /* relax */ + break; + } +} + +void +Editor::set_snap_mode (SnapMode mode) +{ + snap_mode = mode; + vector txt = internationalize (snap_mode_strings); + snap_mode_selector.get_entry()->set_text (txt[(int)mode]); + + instant_save (); +} + +void +Editor::add_location_from_selection () +{ + if (selection->time.empty()) { + return; + } + + if (session == 0 || clicked_trackview == 0) { + return; + } + + jack_nframes_t start = selection->time[clicked_selection].start; + jack_nframes_t end = selection->time[clicked_selection].end; + + Location *location = new Location (start, end, "selection"); + + session->begin_reversible_command (_("add marker")); + session->add_undo (session->locations()->get_memento()); + session->locations()->add (location, true); + session->add_redo_no_execute (session->locations()->get_memento()); + session->commit_reversible_command (); +} + +void +Editor::add_location_from_playhead_cursor () +{ + jack_nframes_t where = session->audible_frame(); + + Location *location = new Location (where, where, "mark", Location::IsMark); + session->begin_reversible_command (_("add marker")); + session->add_undo (session->locations()->get_memento()); + session->locations()->add (location, true); + session->add_redo_no_execute (session->locations()->get_memento()); + session->commit_reversible_command (); +} + + +int +Editor::set_state (const XMLNode& node) +{ + const XMLProperty* prop; + XMLNode* geometry; + int x, y, width, height, xoff, yoff; + + if ((geometry = find_named_node (node, "geometry")) == 0) { + + width = default_width; + height = default_height; + x = 1; + y = 1; + xoff = 0; + yoff = 21; + + } else { + + width = atoi(geometry->property("x_size")->value()); + height = atoi(geometry->property("y_size")->value()); + x = atoi(geometry->property("x_pos")->value()); + y = atoi(geometry->property("y_pos")->value()); + xoff = atoi(geometry->property("x_off")->value()); + yoff = atoi(geometry->property("y_off")->value()); + } + + set_default_size(width, height); + set_uposition(x, y-yoff); + + if ((prop = node.property ("zoom-focus"))) { + set_zoom_focus ((ZoomFocus) atoi (prop->value())); + } + + if ((prop = node.property ("zoom"))) { + set_frames_per_unit (atof (prop->value())); + } + + if ((prop = node.property ("snap-to"))) { + set_snap_to ((SnapType) atoi (prop->value())); + } + + if ((prop = node.property ("snap-mode"))) { + set_snap_mode ((SnapMode) atoi (prop->value())); + } + + if ((prop = node.property ("show-waveforms"))) { + bool yn = (prop->value() == "yes"); + _show_waveforms = !yn; + set_show_waveforms (yn); + } + + if ((prop = node.property ("show-waveforms-recording"))) { + bool yn = (prop->value() == "yes"); + _show_waveforms_recording = !yn; + set_show_waveforms_recording (yn); + } + + if ((prop = node.property ("show-measures"))) { + bool yn = (prop->value() == "yes"); + _show_measures = !yn; + set_show_measures (yn); + } + + if ((prop = node.property ("follow-playhead"))) { + bool yn = (prop->value() == "yes"); + _follow_playhead = !yn; + set_follow_playhead (yn); + } + + if ((prop = node.property ("xfades-visible"))) { + bool yn = (prop->value() == "yes"); + _xfade_visibility = !yn; + set_xfade_visibility (yn); + } + + if ((prop = node.property ("region-list-sort-type"))) { + region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */ + reset_region_list_sort_type(str2regionlistsorttype(prop->value())); + } + + if ((prop = node.property ("mouse-mode"))) { + MouseMode m = str2mousemode(prop->value()); + mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */ + set_mouse_mode (m, true); + } else { + mouse_mode = MouseGain; /* lie, to force the mode switch */ + set_mouse_mode (MouseObject, true); + } + + if ((prop = node.property ("editor-mixer-button"))) { + editor_mixer_button.set_active(prop->value() == "yes"); + } + + return 0; +} + +XMLNode& +Editor::get_state () +{ + XMLNode* node = new XMLNode ("Editor"); + char buf[32]; + + if (is_realized()) { + Gdk_Window win = get_window(); + + int x, y, xoff, yoff, width, height; + win.get_root_origin(x, y); + win.get_position(xoff, yoff); + win.get_size(width, height); + + XMLNode* geometry = new XMLNode ("geometry"); + char buf[32]; + snprintf(buf, sizeof(buf), "%d", width); + geometry->add_property("x_size", string(buf)); + snprintf(buf, sizeof(buf), "%d", height); + geometry->add_property("y_size", string(buf)); + snprintf(buf, sizeof(buf), "%d", x); + geometry->add_property("x_pos", string(buf)); + snprintf(buf, sizeof(buf), "%d", y); + geometry->add_property("y_pos", string(buf)); + snprintf(buf, sizeof(buf), "%d", xoff); + geometry->add_property("x_off", string(buf)); + snprintf(buf, sizeof(buf), "%d", yoff); + geometry->add_property("y_off", string(buf)); + snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast(&canvas_region_list_pane)->gtkobj())); + geometry->add_property("canvas_region_list_pane_pos", string(buf)); + snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast(&track_list_canvas_pane)->gtkobj())); + geometry->add_property("track_list_canvas_pane_pos", string(buf)); + snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast(®ion_selection_vpane)->gtkobj())); + geometry->add_property("region_selection_pane_pos", string(buf)); + snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast(&route_group_vpane)->gtkobj())); + geometry->add_property("route_group_pane_pos", string(buf)); + + node->add_child_nocopy (*geometry); + } + + snprintf (buf, sizeof(buf), "%d", (int) zoom_focus); + node->add_property ("zoom-focus", buf); + snprintf (buf, sizeof(buf), "%f", frames_per_unit); + node->add_property ("zoom", buf); + snprintf (buf, sizeof(buf), "%d", (int) snap_type); + node->add_property ("snap-to", buf); + snprintf (buf, sizeof(buf), "%d", (int) snap_mode); + node->add_property ("snap-mode", buf); + + node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no"); + node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no"); + node->add_property ("show-measures", _show_measures ? "yes" : "no"); + node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no"); + node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no"); + node->add_property ("region-list-sort-type", enum2str(region_list_sort_type)); + node->add_property ("mouse-mode", enum2str(mouse_mode)); + node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no"); + + return *node; +} + + + +TimeAxisView * +Editor::trackview_by_y_position (double y) +{ + TrackViewList::iterator iter; + TimeAxisView *tv; + + for (iter = track_views.begin(); iter != track_views.end(); ++iter) { + + tv = *iter; + + if (tv->hidden()) { + continue; + } + + if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) { + return tv; + } + } + + return 0; +} + +void +Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark) +{ + Location* before = 0; + Location* after = 0; + + if (!session) { + return; + } + + const jack_nframes_t one_second = session->frame_rate(); + const jack_nframes_t one_minute = session->frame_rate() * 60; + + jack_nframes_t presnap = start; + + switch (snap_type) { + case SnapToFrame: + break; + + case SnapToCDFrame: + if (direction) { + start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75); + } else { + start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75); + } + break; + case SnapToSMPTEFrame: + if (direction) { + start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame()); + } else { + start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame()); + } + break; + + case SnapToSMPTESeconds: + if (session->smpte_offset_negative()) + { + start += session->smpte_offset (); + } else { + start -= session->smpte_offset (); + } + if (direction > 0) { + start = (jack_nframes_t) ceil ((double) start / one_second) * one_second; + } else { + start = (jack_nframes_t) floor ((double) start / one_second) * one_second; + } + + if (session->smpte_offset_negative()) + { + start -= session->smpte_offset (); + } else { + start += session->smpte_offset (); + } + break; + + case SnapToSMPTEMinutes: + if (session->smpte_offset_negative()) + { + start += session->smpte_offset (); + } else { + start -= session->smpte_offset (); + } + if (direction) { + start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute; + } else { + start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute; + } + if (session->smpte_offset_negative()) + { + start -= session->smpte_offset (); + } else { + start += session->smpte_offset (); + } + break; + + case SnapToSeconds: + if (direction) { + start = (jack_nframes_t) ceil ((double) start / one_second) * one_second; + } else { + start = (jack_nframes_t) floor ((double) start / one_second) * one_second; + } + break; + + case SnapToMinutes: + if (direction) { + start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute; + } else { + start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute; + } + break; + + case SnapToBar: + start = session->tempo_map().round_to_bar (start, direction); + break; + + case SnapToBeat: + start = session->tempo_map().round_to_beat (start, direction); + break; + + case SnapToAThirtysecondBeat: + start = session->tempo_map().round_to_beat_subdivision (start, 32); + break; + + case SnapToASixteenthBeat: + start = session->tempo_map().round_to_beat_subdivision (start, 16); + break; + + case SnapToAEighthBeat: + start = session->tempo_map().round_to_beat_subdivision (start, 8); + break; + + case SnapToAQuarterBeat: + start = session->tempo_map().round_to_beat_subdivision (start, 4); + break; + + case SnapToAThirdBeat: + start = session->tempo_map().round_to_beat_subdivision (start, 3); + break; + + case SnapToEditCursor: + start = edit_cursor->current_frame; + break; + + case SnapToMark: + if (for_mark) { + return; + } + + before = session->locations()->first_location_before (start); + after = session->locations()->first_location_after (start); + + if (direction < 0) { + if (before) { + start = before->start(); + } else { + start = 0; + } + } else if (direction > 0) { + if (after) { + start = after->start(); + } else { + start = session->current_end_frame(); + } + } else { + if (before) { + if (after) { + /* find nearest of the two */ + if ((start - before->start()) < (after->start() - start)) { + start = before->start(); + } else { + start = after->start(); + } + } else { + start = before->start(); + } + } else if (after) { + start = after->start(); + } else { + /* relax */ + } + } + break; + + case SnapToRegionStart: + case SnapToRegionEnd: + case SnapToRegionSync: + case SnapToRegionBoundary: + if (!region_boundary_cache.empty()) { + vector::iterator i; + + if (direction > 0) { + i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start); + } else { + i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start); + } + + if (i != region_boundary_cache.end()) { + start = *i; + } else { + start = region_boundary_cache.back(); + } + } + break; + } + + switch (snap_mode) { + case SnapNormal: + return; + + case SnapMagnetic: + + if (presnap > start) { + if (presnap > (start + unit_to_frame(snap_threshold))) { + start = presnap; + } + + } else if (presnap < start) { + if (presnap < (start - unit_to_frame(snap_threshold))) { + start = presnap; + } + } + + default: + return; + + } +} + +void +Editor::setup_toolbar () +{ + nstring pixmap_path; + vector mouse_mode_buttons; + + mouse_mode_buttons.push_back (&mouse_move_button); + mouse_mode_buttons.push_back (&mouse_select_button); + mouse_mode_buttons.push_back (&mouse_gain_button); + mouse_mode_buttons.push_back (&mouse_zoom_button); + mouse_mode_buttons.push_back (&mouse_timefx_button); + mouse_mode_buttons.push_back (&mouse_audition_button); + mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons); + + mouse_mode_button_table.set_homogeneous (true); + mouse_mode_button_table.set_col_spacings (2); + mouse_mode_button_table.set_row_spacings (2); + mouse_mode_button_table.set_border_width (5); + + mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1); + mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1); + mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1); + + mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2); + mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2); + mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2); + + mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table)); + mouse_mode_tearoff->set_name ("MouseModeBase"); + + mouse_mode_tearoff->Detach.connect (bind (slot (*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), + static_cast(&mouse_mode_button_table))); + mouse_mode_tearoff->Attach.connect (bind (slot (*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), + static_cast (&mouse_mode_button_table), 1)); + + mouse_move_button.set_name ("MouseModeButton"); + mouse_select_button.set_name ("MouseModeButton"); + mouse_gain_button.set_name ("MouseModeButton"); + mouse_zoom_button.set_name ("MouseModeButton"); + mouse_timefx_button.set_name ("MouseModeButton"); + mouse_audition_button.set_name ("MouseModeButton"); + + ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects")); + ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges")); + ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation")); + ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range")); + ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions")); + ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions")); + + mouse_move_button.unset_flags (GTK_CAN_FOCUS); + mouse_select_button.unset_flags (GTK_CAN_FOCUS); + mouse_gain_button.unset_flags (GTK_CAN_FOCUS); + mouse_zoom_button.unset_flags (GTK_CAN_FOCUS); + mouse_timefx_button.unset_flags (GTK_CAN_FOCUS); + mouse_audition_button.unset_flags (GTK_CAN_FOCUS); + + mouse_select_button.toggled.connect (bind (slot (*this, &Editor::mouse_mode_toggled), Editing::MouseRange)); + mouse_select_button.button_release_event.connect (slot (*this, &Editor::mouse_select_button_release)); + + mouse_move_button.toggled.connect (bind (slot (*this, &Editor::mouse_mode_toggled), Editing::MouseObject)); + mouse_gain_button.toggled.connect (bind (slot (*this, &Editor::mouse_mode_toggled), Editing::MouseGain)); + mouse_zoom_button.toggled.connect (bind (slot (*this, &Editor::mouse_mode_toggled), Editing::MouseZoom)); + mouse_timefx_button.toggled.connect (bind (slot (*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX)); + mouse_audition_button.toggled.connect (bind (slot (*this, &Editor::mouse_mode_toggled), Editing::MouseAudition)); + + // mouse_move_button.set_active (true); + + /* automation control */ + + global_automation_button.set_name ("MouseModeButton"); + automation_mode_button.set_name ("MouseModeButton"); + + automation_box.set_spacing (2); + automation_box.set_border_width (2); + automation_box.pack_start (global_automation_button, false, false); + automation_box.pack_start (automation_mode_button, false, false); + + /* Edit mode */ + + edit_mode_label.set_name ("ToolBarLabel"); + + edit_mode_selector.set_name ("EditModeSelector"); + edit_mode_selector.get_entry()->set_name ("EditModeSelector"); + edit_mode_selector.get_popwin()->set_name ("EditModeSelector"); + + edit_mode_box.set_spacing (3); + edit_mode_box.set_border_width (3); + + /* XXX another disgusting hack because of the way combo boxes size themselves */ + + Gtkmmext::set_usize_to_display_given_text (*edit_mode_selector.get_entry(), "EdgtMode", 2, 10); + edit_mode_selector.set_popdown_strings (internationalize (edit_mode_strings)); + edit_mode_selector.set_value_in_list (true, false); + + edit_mode_box.pack_start (edit_mode_label, false, false); + edit_mode_box.pack_start (edit_mode_selector, false, false); + + edit_mode_selector.get_popwin()->unmap_event.connect (slot (*this, &Editor::edit_mode_selection_done)); + + /* Snap Type */ + + snap_type_label.set_name ("ToolBarLabel"); + + snap_type_selector.set_name ("SnapTypeSelector"); + snap_type_selector.get_entry()->set_name ("SnapTypeSelector"); + snap_type_selector.get_popwin()->set_name ("SnapTypeSelector"); + + snap_type_box.set_spacing (3); + snap_type_box.set_border_width (3); + + /* XXX another disgusting hack because of the way combo boxes size themselves */ + + const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button + Gtkmmext::set_usize_to_display_given_text (*snap_type_selector.get_entry(), "Region bounds", 2+FUDGE, 10); + snap_type_selector.set_popdown_strings (internationalize (snap_type_strings)); + snap_type_selector.set_value_in_list (true, false); + + snap_type_box.pack_start (snap_type_label, false, false); + snap_type_box.pack_start (snap_type_selector, false, false); + + snap_type_selector.get_popwin()->unmap_event.connect (slot (*this, &Editor::snap_type_selection_done)); + + /* Snap mode, not snap type */ + + snap_mode_label.set_name ("ToolBarLabel"); + + snap_mode_selector.set_name ("SnapModeSelector"); + snap_mode_selector.get_entry()->set_name ("SnapModeSelector"); + snap_mode_selector.get_popwin()->set_name ("SnapModeSelector"); + + snap_mode_box.set_spacing (3); + snap_mode_box.set_border_width (3); + + Gtkmmext::set_usize_to_display_given_text (*snap_mode_selector.get_entry(), "SngpMode", 2, 10); + snap_mode_selector.set_popdown_strings (internationalize (snap_mode_strings)); + snap_mode_selector.set_value_in_list (true, false); + + snap_mode_box.pack_start (snap_mode_label, false, false); + snap_mode_box.pack_start (snap_mode_selector, false, false); + + snap_mode_selector.get_popwin()->unmap_event.connect (slot (*this, &Editor::snap_mode_selection_done)); + + /* Zoom focus mode */ + + zoom_focus_label.set_name ("ToolBarLabel"); + + zoom_focus_selector.set_name ("ZoomFocusSelector"); + zoom_focus_selector.get_entry()->set_name ("ZoomFocusSelector"); + zoom_focus_selector.get_popwin()->set_name ("ZoomFocusSelector"); + + zoom_focus_box.set_spacing (3); + zoom_focus_box.set_border_width (3); + + /* XXX another disgusting hack because of the way combo boxes size themselves */ + + Gtkmmext::set_usize_to_display_given_text (*zoom_focus_selector.get_entry(), "Edgt Cursor", 2, 10); + zoom_focus_selector.set_popdown_strings (internationalize (zoom_focus_strings)); + zoom_focus_selector.set_value_in_list (true, false); + + zoom_focus_box.pack_start (zoom_focus_label, false, false); + zoom_focus_box.pack_start (zoom_focus_selector, false, false); + + zoom_focus_selector.get_popwin()->unmap_event.connect (slot (*this, &Editor::zoom_focus_selection_done)); + + /* selection/cursor clocks */ + + toolbar_selection_cursor_label.set_name ("ToolBarLabel"); + selection_start_clock_label.set_name ("ToolBarLabel"); + selection_end_clock_label.set_name ("ToolBarLabel"); + edit_cursor_clock_label.set_name ("ToolBarLabel"); + + selection_start_clock_label.set_text (_("Start:")); + selection_end_clock_label.set_text (_("End:")); + edit_cursor_clock_label.set_text (_("Edit:")); + + toolbar_selection_clock_table.set_border_width (5); + toolbar_selection_clock_table.set_col_spacings (2); + toolbar_selection_clock_table.set_homogeneous (false); + +// toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0); +// toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0); + toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, 0, 0, 0, 0); + +// toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0); +// toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0); + toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, 0, 0); + + +// toolbar_clock_vbox.set_spacing (2); +// toolbar_clock_vbox.set_border_width (10); + /* the editor/mixer button will be enabled at session connect */ + + editor_mixer_button.set_active(false); + editor_mixer_button.set_sensitive(false); + + HBox* hbox = new HBox; + + hbox->pack_start (editor_mixer_button, false, false); + hbox->pack_start (toolbar_selection_clock_table, false, false); + hbox->pack_start (zoom_indicator_vbox, false, false); + hbox->pack_start (zoom_focus_box, false, false); + hbox->pack_start (snap_type_box, false, false); + hbox->pack_start (snap_mode_box, false, false); + hbox->pack_start (edit_mode_box, false, false); + + VBox *vbox = manage (new VBox); + + vbox->set_spacing (3); + vbox->set_border_width (3); + + HBox *nbox = manage (new HBox); + + nudge_forward_button.clicked.connect (bind (slot (*this, &Editor::nudge_forward), false)); + nudge_backward_button.clicked.connect (bind (slot (*this, &Editor::nudge_backward), false)); + + nbox->pack_start (nudge_backward_button, false, false); + nbox->pack_start (nudge_forward_button, false, false); + nbox->pack_start (nudge_clock, false, false, 5); + + nudge_label.set_name ("ToolBarLabel"); + + vbox->pack_start (nudge_label, false, false); + vbox->pack_start (*nbox, false, false); + + hbox->pack_start (*vbox, false, false); + + hbox->show_all (); + + tools_tearoff = new TearOff (*hbox); + tools_tearoff->set_name ("MouseModeBase"); + + tools_tearoff->Detach.connect (bind (slot (*this, &Editor::detach_tearoff), static_cast(&toolbar_hbox), + static_cast(hbox))); + tools_tearoff->Attach.connect (bind (slot (*this, &Editor::reattach_tearoff), static_cast (&toolbar_hbox), + static_cast (hbox), 0)); + + toolbar_hbox.set_spacing (8); + toolbar_hbox.set_border_width (2); + + toolbar_hbox.pack_start (*tools_tearoff, false, false); + toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false); + + toolbar_base.set_name ("ToolBarBase"); + toolbar_base.add (toolbar_hbox); + + toolbar_frame.set_shadow_type (GTK_SHADOW_OUT); + toolbar_frame.set_name ("BaseFrame"); + toolbar_frame.add (toolbar_base); +} + +gint +Editor::_autoscroll_canvas (void *arg) +{ + return ((Editor *) arg)->autoscroll_canvas (); +} + +gint +Editor::autoscroll_canvas () +{ + jack_nframes_t new_frame; + bool keep_calling = true; + + if (autoscroll_direction < 0) { + if (leftmost_frame < autoscroll_distance) { + new_frame = 0; + } else { + new_frame = leftmost_frame - autoscroll_distance; + } + } else { + if (leftmost_frame > max_frames - autoscroll_distance) { + new_frame = max_frames; + } else { + new_frame = leftmost_frame + autoscroll_distance; + } + } + + if (new_frame != leftmost_frame) { + reposition_x_origin (new_frame); + } + + if (new_frame == 0 || new_frame == max_frames) { + /* we are done */ + return FALSE; + } + + autoscroll_cnt++; + + if (autoscroll_cnt == 1) { + + /* connect the timeout so that we get called repeatedly */ + + autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this); + keep_calling = false; + + } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) { + + /* after about a while, speed up a bit by changing the timeout interval */ + + autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this); + keep_calling = false; + + } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) { + + /* after about another while, speed up some more */ + + autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this); + keep_calling = false; + + } else if (autoscroll_cnt >= 30) { + + /* we've been scrolling for a while ... crank it up */ + + autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit); + } + + return keep_calling; +} + +void +Editor::start_canvas_autoscroll (int dir) +{ + if (!session) { + return; + } + + stop_canvas_autoscroll (); + + autoscroll_direction = dir; + autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0); + autoscroll_cnt = 0; + + /* do it right now, which will start the repeated callbacks */ + + autoscroll_canvas (); +} + +void +Editor::stop_canvas_autoscroll () +{ + if (autoscroll_timeout_tag >= 0) { + gtk_timeout_remove (autoscroll_timeout_tag); + autoscroll_timeout_tag = -1; + } +} + +int +Editor::convert_drop_to_paths (vector& paths, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time) + +{ + string spath; + char *path; + int state; + gchar *tname = gdk_atom_name (data->type); + + if (session == 0 || strcmp (tname, "text/plain") != 0) { + return -1; + } + + /* Parse the "uri-list" format that Nautilus provides, + where each pathname is delimited by \r\n + */ + + path = (char *) data->data; + state = 0; + + for (int n = 0; n < data->length; ++n) { + + switch (state) { + case 0: + if (path[n] == '\r') { + state = 1; + } else { + spath += path[n]; + } + break; + case 1: + if (path[n] == '\n') { + paths.push_back (spath); + spath = ""; + state = 0; + } else { + warning << _("incorrectly formatted URI list, ignored") + << endmsg; + return -1; + } + break; + } + } + + /* nautilus and presumably some other file managers prefix even text/plain with file:// */ + + for (vector::iterator p = paths.begin(); p != paths.end(); ++p) { + + // cerr << "dropped text was " << *p << endl; + + url_decode (*p); + + // cerr << "decoded was " << *p << endl; + + if ((*p).substr (0,7) == "file://") { + (*p) = (*p).substr (7); + } + } + + return 0; +} + +void +Editor::track_canvas_drag_data_received (GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time) +{ + TimeAxisView* tvp; + AudioTimeAxisView* tv; + double cy; + vector paths; + string spath; + GdkEvent ev; + jack_nframes_t frame; + + if (convert_drop_to_paths (paths, context, x, y, data, info, time)) { + goto out; + } + + /* D-n-D coordinates are window-relative, so convert to "world" coordinates + */ + + double wx; + double wy; + + gtk_canvas_window_to_world (GTK_CANVAS(track_gtk_canvas), (double) x, (double) y, &wx, &wy); + + ev.type = GDK_BUTTON_RELEASE; + ev.button.x = wx; + ev.button.y = wy; + + frame = event_frame (&ev, 0, &cy); + + snap_to (frame); + + if ((tvp = trackview_by_y_position (cy)) == 0) { + + /* drop onto canvas background: create a new track */ + + insert_paths_as_new_tracks (paths, false); + + + } else if ((tv = dynamic_cast(tvp)) != 0) { + + /* check that its an audio track, not a bus */ + + if (tv->get_diskstream()) { + + for (vector::iterator p = paths.begin(); p != paths.end(); ++p) { + insert_sndfile_into (*p, true, tv, frame); + } + } + + } + + out: + gtk_drag_finish (context, TRUE, FALSE, time); +} + +void +Editor::new_tempo_section () + +{ +} + +void +Editor::map_transport_state () +{ + ENSURE_GUI_THREAD (slot (*this, &Editor::map_transport_state)); + + if (session->transport_stopped()) { + have_pending_keyboard_selection = false; + } +} + +/* UNDO/REDO */ + +Editor::State::State () +{ + selection = new Selection; +} + +Editor::State::~State () +{ + delete selection; +} + +UndoAction +Editor::get_memento () const +{ + State *state = new State; + + store_state (*state); + return bind (slot (*(const_cast(this)), &Editor::restore_state), state); +} + +void +Editor::store_state (State& state) const +{ + *state.selection = *selection; +} + +void +Editor::restore_state (State *state) +{ + if (*selection == *state->selection) { + return; + } + + *selection = *state->selection; + time_selection_changed (); + region_selection_changed (); + + /* XXX other selection change handlers? */ +} + +void +Editor::begin_reversible_command (string name) +{ + if (session) { + UndoAction ua = get_memento(); + session->begin_reversible_command (name, &ua); + } +} + +void +Editor::commit_reversible_command () +{ + if (session) { + UndoAction ua = get_memento(); + session->commit_reversible_command (&ua); + } +} + +void +Editor::flush_track_canvas () +{ + /* I don't think this is necessary, and only causes more problems. + I'm commenting it out + and if the imageframe folks don't have any issues, we can take + out this method entirely + */ + + //gtk_canvas_update_now (GTK_CANVAS(track_gtk_canvas)); + //gtk_main_iteration (); +} + +void +Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove) +{ + if (!clicked_trackview) { + return; + } + + if (with_undo) { + begin_reversible_command (_("set selected trackview")); + } + + if (add) { + + if (selection->selected (clicked_trackview)) { + if (!no_remove) { + selection->remove (clicked_trackview); + } + } else { + selection->add (clicked_trackview); + } + + } else { + + if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) { + /* no commit necessary */ + return; + } + + selection->set (clicked_trackview); + } + + if (with_undo) { + commit_reversible_command (); + } +} + +void +Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove) +{ + if (!clicked_control_point) { + return; + } + + if (with_undo) { + begin_reversible_command (_("set selected control point")); + } + + if (add) { + + } else { + + } + + if (with_undo) { + commit_reversible_command (); + } +} + +void +Editor::set_selected_regionview_from_click (bool add, bool no_track_remove) +{ + if (!clicked_regionview) { + return; + } + + AudioTimeAxisView* atv = dynamic_cast(&clicked_regionview->get_time_axis_view()); + + if (!atv) { + return; + } + + RouteGroup* group = atv->route().edit_group(); + vector all_equivalent_regions; + + if (group && group->is_active()) { + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + + AudioTimeAxisView* tatv; + + if ((tatv = dynamic_cast (*i)) != 0) { + + if (tatv->route().edit_group() != group) { + continue; + } + + AudioPlaylist* pl; + vector results; + AudioRegionView* marv; + DiskStream* ds; + + if ((ds = tatv->get_diskstream()) == 0) { + /* bus */ + continue; + } + + if ((pl = ds->playlist()) != 0) { + pl->get_equivalent_regions (clicked_regionview->region, + results); + } + + for (vector::iterator ir = results.begin(); ir != results.end(); ++ir) { + if ((marv = tatv->view->find_view (**ir)) != 0) { + all_equivalent_regions.push_back (marv); + } + } + + } + } + + } else { + + all_equivalent_regions.push_back (clicked_regionview); + + } + + begin_reversible_command (_("set selected regionview")); + + if (add) { + + if (clicked_regionview->get_selected()) { + if (group && group->is_active() && selection->audio_regions.size() > 1) { + /* reduce selection down to just the one clicked */ + selection->set (clicked_regionview); + } else { + selection->remove (clicked_regionview); + } + } else { + selection->add (all_equivalent_regions); + } + + set_selected_track_from_click (add, false, no_track_remove); + + } else { + + // karsten wiese suggested these two lines to make + // a selected region rise to the top. but this + // leads to a mismatch between actual layering + // and visual layering. resolution required .... + // + // gtk_canvas_item_raise_to_top (clicked_regionview->get_canvas_group()); + // gtk_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display); + + if (clicked_regionview->get_selected()) { + /* no commit necessary: we are the one selected. */ + return; + + } else { + + selection->set (all_equivalent_regions); + set_selected_track_from_click (add, false, false); + } + } + + commit_reversible_command () ; +} + +void +Editor::set_selected_regionview_from_region_list (Region& r, bool add) +{ + vector all_equivalent_regions; + AudioRegion* region; + + if ((region = dynamic_cast(&r)) == 0) { + return; + } + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + + AudioTimeAxisView* tatv; + + if ((tatv = dynamic_cast (*i)) != 0) { + + AudioPlaylist* pl; + vector results; + AudioRegionView* marv; + DiskStream* ds; + + if ((ds = tatv->get_diskstream()) == 0) { + /* bus */ + continue; + } + + if ((pl = ds->playlist()) != 0) { + pl->get_region_list_equivalent_regions (*region, results); + } + + for (vector::iterator ir = results.begin(); ir != results.end(); ++ir) { + if ((marv = tatv->view->find_view (**ir)) != 0) { + all_equivalent_regions.push_back (marv); + } + } + + } + } + + begin_reversible_command (_("set selected regions")); + + if (add) { + + selection->add (all_equivalent_regions); + + } else { + + selection->set (all_equivalent_regions); + } + + commit_reversible_command () ; +} + +gint +Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r) +{ + AudioRegionView* rv; + AudioRegion* ar; + + if ((ar = dynamic_cast (r)) == 0) { + return TRUE; + } + + if ((rv = sv->find_view (*ar)) == 0) { + return TRUE; + } + + /* don't reset the selection if its something other than + a single other region. + */ + + if (selection->audio_regions.size() > 1) { + return TRUE; + } + + begin_reversible_command (_("set selected regions")); + + selection->set (rv); + + commit_reversible_command () ; + + return TRUE; +} + +void +Editor::set_edit_group_solo (Route& route, bool yn) +{ + RouteGroup *edit_group; + + if ((edit_group = route.edit_group()) != 0) { + edit_group->apply (&Route::set_solo, yn, this); + } else { + route.set_solo (yn, this); + } +} + +void +Editor::set_edit_group_mute (Route& route, bool yn) +{ + RouteGroup *edit_group = 0; + + if ((edit_group == route.edit_group()) != 0) { + edit_group->apply (&Route::set_mute, yn, this); + } else { + route.set_mute (yn, this); + } +} + +void +Editor::set_edit_menu (Menu& menu) +{ + edit_menu = &menu; + edit_menu->map_.connect (slot (*this, &Editor::edit_menu_map_handler)); +} + +void +Editor::edit_menu_map_handler () +{ + using namespace Menu_Helpers; + MenuList& edit_items = edit_menu->items(); + string label; + + /* Nuke all the old items */ + + edit_items.clear (); + + if (session == 0) { + return; + } + + if (session->undo_depth() == 0) { + label = _("Undo"); + } else { + label = compose(_("Undo (%1)"), session->next_undo()); + } + + edit_items.push_back (MenuElem (label, bind (slot (*this, &Editor::undo), 1U))); + + if (session->undo_depth() == 0) { + edit_items.back()->set_sensitive (false); + } + + if (session->redo_depth() == 0) { + label = _("Redo"); + } else { + label = compose(_("Redo (%1)"), session->next_redo()); + } + + edit_items.push_back (MenuElem (label, bind (slot (*this, &Editor::redo), 1U))); + if (session->redo_depth() == 0) { + edit_items.back()->set_sensitive (false); + } + + vector mitems; + + edit_items.push_back (SeparatorElem()); + edit_items.push_back (MenuElem (_("Cut"), slot (*this, &Editor::cut))); + mitems.push_back (edit_items.back()); + edit_items.push_back (MenuElem (_("Copy"), slot (*this, &Editor::copy))); + mitems.push_back (edit_items.back()); + edit_items.push_back (MenuElem (_("Paste"), bind (slot (*this, &Editor::paste), 1.0f))); + mitems.push_back (edit_items.back()); + edit_items.push_back (SeparatorElem()); + edit_items.push_back (MenuElem (_("Align"), bind (slot (*this, &Editor::align), ARDOUR::SyncPoint))); + mitems.push_back (edit_items.back()); + edit_items.push_back (MenuElem (_("Align Relative"), bind (slot (*this, &Editor::align_relative), ARDOUR::SyncPoint))); + mitems.push_back (edit_items.back()); + edit_items.push_back (SeparatorElem()); + + if (selection->empty()) { + for (vector::iterator i = mitems.begin(); i != mitems.end(); ++i) { + (*i)->set_sensitive (false); + } + } + + Menu* import_menu = manage (new Menu()); + import_menu->set_name ("ArdourContextMenu"); + MenuList& import_items = import_menu->items(); + + import_items.push_back (MenuElem (_("... as new track"), bind (slot (*this, &Editor::import_audio), true))); + import_items.push_back (MenuElem (_("... as new region"), bind (slot (*this, &Editor::import_audio), false))); + + Menu* embed_menu = manage (new Menu()); + embed_menu->set_name ("ArdourContextMenu"); + MenuList& embed_items = embed_menu->items(); + + embed_items.push_back (MenuElem (_("... as new track"), bind (slot (*this, &Editor::insert_sndfile), true))); + embed_items.push_back (MenuElem (_("... as new region"), slot (*this, &Editor::embed_audio))); + + edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu)); + edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu)); + edit_items.push_back (SeparatorElem()); + + edit_items.push_back (MenuElem (_("Remove last capture"), slot (*this, &Editor::remove_last_capture))); + if (!session->have_captured()) { + edit_items.back()->set_sensitive (false); + } +} + +void +Editor::duplicate_dialog (bool dup_region) +{ + if (dup_region) { + if (clicked_regionview == 0) { + return; + } + } else { + if (selection->time.length() == 0) { + return; + } + } + + ArdourDialog win ("duplicate dialog"); + Entry entry; + Label label (_("Duplicate how many times?")); + HBox hbox; + HBox button_box; + Button ok_button (_("OK")); + Button cancel_button (_("Cancel")); + VBox vbox; + + button_box.set_spacing (7); + set_usize_to_display_given_text (ok_button, _("Cancel"), 20, 15); // this is cancel on purpose + set_usize_to_display_given_text (cancel_button, _("Cancel"), 20, 15); + button_box.pack_end (ok_button, false, false); + button_box.pack_end (cancel_button, false, false); + + hbox.set_spacing (5); + hbox.pack_start (label); + hbox.pack_start (entry, true, true); + + vbox.set_spacing (5); + vbox.set_border_width (5); + vbox.pack_start (hbox); + vbox.pack_start (button_box); + + win.add (vbox); + win.set_position (GTK_WIN_POS_MOUSE); + win.show_all (); + + ok_button.clicked.connect (bind (slot (win, &ArdourDialog::stop), 0)); + entry.activate.connect (bind (slot (win, &ArdourDialog::stop), 0)); + cancel_button.clicked.connect (bind (slot (win, &ArdourDialog::stop), 1)); + + entry.focus_in_event.connect (slot (ARDOUR_UI::generic_focus_in_event)); + entry.focus_out_event.connect (slot (ARDOUR_UI::generic_focus_out_event)); + + entry.set_text ("1"); + set_usize_to_display_given_text (entry, X_("12345678"), 20, 15); + entry.select_region (0, entry.get_text_length()); + + win.set_position (GTK_WIN_POS_MOUSE); + win.realize (); + win.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + + entry.grab_focus (); + + win.run (); + + if (win.run_status() != 0) { + return; + } + + string text = entry.get_text(); + float times; + + if (sscanf (text.c_str(), "%f", ×) == 1) { + if (dup_region) { + AudioRegionSelection regions; + regions.add (clicked_regionview); + duplicate_some_regions (regions, times); + } else { + duplicate_selection (times); + } + } +} + +void +Editor::show_verbose_canvas_cursor () +{ + gtk_canvas_item_raise_to_top (verbose_canvas_cursor); + gtk_canvas_item_show (verbose_canvas_cursor); + verbose_cursor_visible = true; +} + +void +Editor::hide_verbose_canvas_cursor () +{ + gtk_canvas_item_hide (verbose_canvas_cursor); + verbose_cursor_visible = false; +} + +void +Editor::set_verbose_canvas_cursor (string txt, double x, double y) +{ + /* XXX get origin of canvas relative to root window, + add x and y and check compared to gdk_screen_{width,height} + */ + gtk_canvas_item_set (verbose_canvas_cursor, "text", txt.c_str(), "x", x, "y", y, NULL); +} + +void +Editor::set_verbose_canvas_cursor_text (string txt) +{ + gtk_canvas_item_set (verbose_canvas_cursor, "text", txt.c_str(), NULL); +} + +gint +Editor::edit_mode_selection_done (GdkEventAny *ev) +{ + if (session == 0) { + return FALSE; + } + + string choice = edit_mode_selector.get_entry()->get_text(); + EditMode mode = Slide; + + if (choice == _("Splice")) { + mode = Splice; + } else if (choice == _("Slide")) { + mode = Slide; + } + + session->set_edit_mode (mode); + + return FALSE; +} + +gint +Editor::snap_type_selection_done (GdkEventAny *ev) +{ + if (session == 0) { + return FALSE; + } + + string choice = snap_type_selector.get_entry()->get_text(); + SnapType snaptype = SnapToFrame; + + if (choice == _("Beats/3")) { + snaptype = SnapToAThirdBeat; + } else if (choice == _("Beats/4")) { + snaptype = SnapToAQuarterBeat; + } else if (choice == _("Beats/8")) { + snaptype = SnapToAEighthBeat; + } else if (choice == _("Beats/16")) { + snaptype = SnapToASixteenthBeat; + } else if (choice == _("Beats/32")) { + snaptype = SnapToAThirtysecondBeat; + } else if (choice == _("Beats")) { + snaptype = SnapToBeat; + } else if (choice == _("Bars")) { + snaptype = SnapToBar; + } else if (choice == _("Marks")) { + snaptype = SnapToMark; + } else if (choice == _("Edit Cursor")) { + snaptype = SnapToEditCursor; + } else if (choice == _("Region starts")) { + snaptype = SnapToRegionStart; + } else if (choice == _("Region ends")) { + snaptype = SnapToRegionEnd; + } else if (choice == _("Region bounds")) { + snaptype = SnapToRegionBoundary; + } else if (choice == _("Region syncs")) { + snaptype = SnapToRegionSync; + } else if (choice == _("CD Frames")) { + snaptype = SnapToCDFrame; + } else if (choice == _("SMPTE Frames")) { + snaptype = SnapToSMPTEFrame; + } else if (choice == _("SMPTE Seconds")) { + snaptype = SnapToSMPTESeconds; + } else if (choice == _("SMPTE Minutes")) { + snaptype = SnapToSMPTEMinutes; + } else if (choice == _("Seconds")) { + snaptype = SnapToSeconds; + } else if (choice == _("Minutes")) { + snaptype = SnapToMinutes; + } else if (choice == _("None")) { + snaptype = SnapToFrame; + } + + set_snap_to (snaptype); + + return FALSE; +} + +gint +Editor::snap_mode_selection_done (GdkEventAny *ev) +{ + if(session == 0) return FALSE; + + string choice = snap_mode_selector.get_entry()->get_text(); + SnapMode mode = SnapNormal; + + if (choice == _("Normal")) { + mode = SnapNormal; + } else if (choice == _("Magnetic")) { + mode = SnapMagnetic; + } + + set_snap_mode (mode); + + return FALSE; +} + +gint +Editor::zoom_focus_selection_done (GdkEventAny *ev) +{ + if (session == 0) { + return FALSE; + } + + string choice = zoom_focus_selector.get_entry()->get_text(); + ZoomFocus focus_type = ZoomFocusLeft; + + if (choice == _("Left")) { + focus_type = ZoomFocusLeft; + } else if (choice == _("Right")) { + focus_type = ZoomFocusRight; + } else if (choice == _("Center")) { + focus_type = ZoomFocusCenter; + } else if (choice == _("Playhead")) { + focus_type = ZoomFocusPlayhead; + } else if (choice == _("Edit Cursor")) { + focus_type = ZoomFocusEdit; + } + + set_zoom_focus (focus_type); + + return FALSE; +} + +gint +Editor::edit_controls_button_release (GdkEventButton* ev) +{ + if (Keyboard::is_context_menu_event (ev)) { + ARDOUR_UI::instance()->add_route (); + } + return TRUE; +} + +void +Editor::track_selection_changed () +{ + switch (selection->tracks.size()){ + case 0: + break; + default: + set_selected_mixer_strip (*(selection->tracks.front())); + break; + } + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + (*i)->set_selected (false); + if (mouse_mode == MouseRange) { + (*i)->hide_selection (); + } + } + + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + (*i)->set_selected (true); + if (mouse_mode == MouseRange) { + (*i)->show_selection (selection->time); + } + } +} + +void +Editor::time_selection_changed () +{ + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + (*i)->hide_selection (); + } + + if (selection->tracks.empty()) { + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + (*i)->show_selection (selection->time); + } + } else { + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + (*i)->show_selection (selection->time); + } + } +} + +void +Editor::region_selection_changed () +{ + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + (*i)->set_selected_regionviews (selection->audio_regions); + } +} + +void +Editor::point_selection_changed () +{ + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + (*i)->set_selected_points (selection->points); + } +} + +void +Editor::run_sub_event_loop () +{ + Keyboard::the_keyboard().allow_focus (true); + sub_event_loop_status = 0; + Main::run (); +} + +void +Editor::finish_sub_event_loop (int status) +{ + Main::quit (); + Keyboard::the_keyboard().allow_focus (false); + sub_event_loop_status = status; +} + +gint +Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status) +{ + finish_sub_event_loop (status); + return TRUE; +} + +gint +Editor::mouse_select_button_release (GdkEventButton* ev) +{ + /* this handles just right-clicks */ + + if (ev->button != 3) { + return FALSE; + } + + return TRUE; +} + +Editor::TrackViewList * +Editor::get_valid_views (TimeAxisView* track, RouteGroup* group) +{ + TrackViewList *v; + TrackViewList::iterator i; + + v = new TrackViewList; + + if (track == 0 && group == 0) { + + /* all views */ + + for (i = track_views.begin(); i != track_views.end (); ++i) { + v->push_back (*i); + } + + } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) { + + /* just the view for this track + */ + + v->push_back (track); + + } else { + + /* views for all tracks in the edit group */ + + for (i = track_views.begin(); i != track_views.end (); ++i) { + + if (group == 0 || (*i)->edit_group() == group) { + v->push_back (*i); + } + } + } + + return v; +} + +void +Editor::set_zoom_focus (ZoomFocus f) +{ + if (zoom_focus != f) { + zoom_focus = f; + vector txt = internationalize (zoom_focus_strings); + zoom_focus_selector.get_entry()->set_text (txt[(int)f]); + ZoomFocusChanged (); /* EMIT_SIGNAL */ + + instant_save (); + } +} + +void +Editor::ensure_float (Window& win) +{ + win.set_transient_for (*this); +} + +void +Editor::pane_allocation_handler (GtkAllocation *alloc, Gtk::Paned* which) +{ + /* recover or initialize pane positions. do this here rather than earlier because + we don't want the positions to change the child allocations, which they seem to do. + */ + + int pos; + XMLProperty* prop; + char buf[32]; + XMLNode* node = ARDOUR_UI::instance()->editor_settings(); + int width, height; + static int32_t done[4] = { 0, 0, 0, 0 }; + XMLNode* geometry; + + if ((geometry = find_named_node (*node, "geometry")) == 0) { + width = default_width; + height = default_height; + } else { + width = atoi(geometry->property("x_size")->value()); + height = atoi(geometry->property("y_size")->value()); + } + + if (which == static_cast (&track_list_canvas_pane)) { + + if (done[0]) { + return; + } + + if (!geometry || (prop = geometry->property("track_list_canvas_pane_pos")) == 0) { + pos = 75; + snprintf (buf, sizeof(buf), "%d", pos); + } else { + pos = atoi (prop->value()); + } + + if ((done[0] = GTK_WIDGET(track_list_canvas_pane.gtkobj())->allocation.width > pos)) { + track_list_canvas_pane.set_position (pos); + } + + } else if (which == static_cast (&canvas_region_list_pane)) { + + if (done[1]) { + return; + } + + if (!geometry || (prop = geometry->property("canvas_region_list_pane_pos")) == 0) { + pos = width - (95 * 2); + snprintf (buf, sizeof(buf), "%d", pos); + } else { + pos = atoi (prop->value()); + } + + if ((done[1] = GTK_WIDGET(canvas_region_list_pane.gtkobj())->allocation.width > pos)) { + canvas_region_list_pane.set_position (pos); + } + + } else if (which == static_cast (&route_group_vpane)) { + + if (done[2]) { + return; + } + + if (!geometry || (prop = geometry->property("route_group_pane_pos")) == 0) { + pos = width - (95 * 2); + snprintf (buf, sizeof(buf), "%d", pos); + } else { + pos = atoi (prop->value()); + } + + if ((done[2] = GTK_WIDGET(route_group_vpane.gtkobj())->allocation.height > pos)) { + route_group_vpane.set_position (pos); + } + + } else if (which == static_cast (®ion_selection_vpane)) { + + if (done[3]) { + return; + } + + if (!geometry || (prop = geometry->property("region_selection_pane_pos")) == 0) { + pos = width - (95 * 2); + snprintf (buf, sizeof(buf), "%d", pos); + } else { + pos = atoi (prop->value()); + } + + if ((done[3] = GTK_WIDGET(region_selection_vpane.gtkobj())->allocation.height > pos)) { + region_selection_vpane.set_position (pos); + } + } +} + +void +Editor::detach_tearoff (Gtk::Box* b, Gtk::Widget* w) +{ + if (tools_tearoff->torn_off() && + mouse_mode_tearoff->torn_off()) { + top_hbox.remove (toolbar_frame); + } + + ensure_float (*w->get_toplevel()); +} + +void +Editor::reattach_tearoff (Gtk::Box* b, Gtk::Widget* w, int32_t n) +{ + if (toolbar_frame.get_parent() == 0) { + top_hbox.pack_end (toolbar_frame); + } +} + +void +Editor::set_show_measures (bool yn) +{ + if (_show_measures != yn) { + hide_measures (); + + if ((_show_measures = yn) == true) { + draw_measures (); + } + DisplayControlChanged (ShowMeasures); + instant_save (); + } +} + +void +Editor::set_follow_playhead (bool yn) +{ + if (_follow_playhead != yn) { + if ((_follow_playhead = yn) == true) { + /* catch up */ + update_current_screen (); + } + DisplayControlChanged (FollowPlayhead); + instant_save (); + } +} + +void +Editor::toggle_xfade_active (Crossfade* xfade) +{ + xfade->set_active (!xfade->active()); +} + +void +Editor::toggle_xfade_length (Crossfade* xfade) +{ + xfade->set_follow_overlap (!xfade->following_overlap()); +} + +void +Editor::edit_xfade (Crossfade* xfade) +{ + CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0); + + ensure_float (cew); + + cew.ok_button.clicked.connect (bind (slot (cew, &ArdourDialog::stop), 1)); + cew.cancel_button.clicked.connect (bind (slot (cew, &ArdourDialog::stop), 0)); + cew.delete_event.connect (slot (cew, &ArdourDialog::wm_doi_event_stop)); + + cew.run (); + + if (cew.run_status() == 1) { + cew.apply (); + xfade->StateChanged (Change (~0)); + } +} + +PlaylistSelector& +Editor::playlist_selector () const +{ + return *_playlist_selector; +} + +jack_nframes_t +Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next) +{ + jack_nframes_t ret; + + ret = nudge_clock.current_duration (pos); + next = ret + 1; /* XXXX fix me */ + + return ret; +} + +void +Editor::end_location_changed (Location* location) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &Editor::end_location_changed), location)); + track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit); +} + +int +Editor::playlist_deletion_dialog (Playlist* pl) +{ + ArdourDialog dialog ("playlist deletion dialog"); + Label label (compose (_("Playlist %1 is currently unused.\n" + "If left alone, no audio files used by it will be cleaned.\n" + "If deleted, audio files used by it alone by will cleaned."), + pl->name())); + HBox button_box; + Button del_button (_("Delete playlist")); + Button keep_button (_("Keep playlist")); + Button abort_button (_("Cancel cleanup")); + VBox vbox; + + button_box.set_spacing (7); + button_box.set_homogeneous (true); + button_box.pack_end (del_button, false, false); + button_box.pack_end (keep_button, false, false); + button_box.pack_end (abort_button, false, false); + + vbox.set_spacing (5); + vbox.set_border_width (5); + vbox.pack_start (label); + vbox.pack_start (button_box); + + dialog.add (vbox); + dialog.set_position (GTK_WIN_POS_CENTER); + dialog.show_all (); + + del_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 0)); + keep_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 1)); + abort_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 2)); + + dialog.realize (); + dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + + dialog.run (); + + switch (dialog.run_status()) { + case 1: + /* keep the playlist */ + return 1; + break; + case 0: + /* delete the playlist */ + return 0; + break; + case 2: + /* abort cleanup */ + return -1; + break; + default: + /* keep the playlist */ + return 1; + } +} + +bool +Editor::audio_region_selection_covers (jack_nframes_t where) +{ + for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) { + if ((*a)->region.covers (where)) { + return true; + } + } + + return false; +} + +void +Editor::prepare_for_cleanup () +{ + cut_buffer->clear_audio_regions (); + cut_buffer->clear_playlists (); + + selection->clear_audio_regions (); + selection->clear_playlists (); +} + +void +Editor::init_colormap () +{ + for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) { + pair newpair; + + newpair.first = (ColorID) x; + newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255); + color_map.insert (newpair); + } +} + +Location* +Editor::transport_loop_location() +{ + if (session) { + return session->locations()->auto_loop_location(); + } else { + return 0; + } +} + +Location* +Editor::transport_punch_location() +{ + if (session) { + return session->locations()->auto_punch_location(); + } else { + return 0; + } +} diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h new file mode 100644 index 0000000000..9f90c9f4a2 --- /dev/null +++ b/gtk2_ardour/editor.h @@ -0,0 +1,1823 @@ +/* + Copyright (C) 2000-2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_editor_h__ +#define __ardour_editor_h__ + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "keyboard_target.h" +#include "audio_clock.h" +#include "gtk-custom-ruler.h" +#include "ardour_dialog.h" +#include "public_editor.h" +#include "editing.h" +#include "enums.h" +#include "region_selection.h" + +namespace Gtkmmext { + class TearOff; +} + +namespace LinuxAudioSystems { + class AudioEngine; +} + +namespace ARDOUR { + class DiskStream; + class RouteGroup; + class Source; + class Playlist; + class Region; + class Location; + class TempoSection; + class NamedSelection; + class Session; + class AudioFilter; + class Crossfade; +} + +namespace LADSPA { + class Plugin; +} + +class TimeAxisView; +class AudioTimeAxisView; +class AutomationTimeAxisView; +class AudioRegionView; +class CrossfadeView; +class PluginSelector; +class PlaylistSelector; +class Marker; +class GroupedButtons; +class AutomationLine; +class UIExportSpecification; +class ExportDialog; +class Selection; +class TimeSelection; +class TrackSelection; +class AutomationSelection; +class MixerStrip; +class SoundFileSelector; +class StreamView; +class ControlPoint; + +/* */ +class ImageFrameView; +class ImageFrameTimeAxisView; +class ImageFrameTimeAxis; +class MarkerTimeAxis ; +class MarkerView ; +class ImageFrameSocketHandler ; +class TimeAxisViewItem ; +/* */ + + +class Editor : public PublicEditor +{ + public: + Editor (ARDOUR::AudioEngine&); + ~Editor (); + + void connect_to_session (ARDOUR::Session *); + ARDOUR::Session* current_session() const { return session; } + + jack_nframes_t leftmost_position() const { return leftmost_frame; } + jack_nframes_t current_page_frames() const { + return (jack_nframes_t) floor (canvas_width * frames_per_unit); + } + + void set_snap_to (Editing::SnapType); + void set_snap_mode (Editing::SnapMode); + void set_snap_threshold (double pixel_distance) {snap_threshold = pixel_distance;} + + void undo (uint32_t n = 1); + void redo (uint32_t n = 1); + + XMLNode& get_state (); + int set_state (const XMLNode& ); + + void set_mouse_mode (Editing::MouseMode, bool force=true); + void step_mouse_mode (bool next); + Editing::MouseMode current_mouse_mode () { return mouse_mode; } + + void add_imageframe_time_axis(std::string track_name, void*) ; + void add_imageframe_marker_time_axis(std::string track_name, TimeAxisView* marked_track, void*) ; + void connect_to_image_compositor() ; + void scroll_timeaxis_to_imageframe_item(const TimeAxisViewItem* item) ; + TimeAxisView* get_named_time_axis(std::string name) ; + /* */ + + /* public access to auditioning */ + + bool consider_auditioning (ARDOUR::AudioRegion*); + + /* option editor-access */ + + void set_show_waveforms (bool yn); + bool show_waveforms() const { return _show_waveforms; } + + void set_show_waveforms_recording (bool yn); + bool show_waveforms_recording() const { return _show_waveforms_recording; } + + /* things that need to be public to be used in the main menubar */ + + void new_region_from_selection (); + void separate_region_from_selection (); + void toggle_playback (bool with_abort); + + /* undo related */ + + void set_edit_menu (Gtk::Menu&); + + jack_nframes_t unit_to_frame (double unit) { + return (jack_nframes_t) rint (unit * frames_per_unit); + } + + double frame_to_unit (jack_nframes_t frame) { + return rint ((double) frame / (double) frames_per_unit); + } + + double frame_to_unit (double frame) { + return rint (frame / frames_per_unit); + } + + /* NOTE: these functions assume that the "pixel" coordinate is + the result of using the world->canvas affine transform on a + world coordinate. These coordinates already take into + account any scrolling carried out by adjusting the + xscroll_adjustment. + */ + + jack_nframes_t pixel_to_frame (double pixel) { + + /* pixel can be less than zero when motion events + are processed. since we've already run the world->canvas + affine, that means that the location *really* is "off + to the right" and thus really is "before the start". + */ + + if (pixel >= 0) { + return (jack_nframes_t) rint (pixel * frames_per_unit * GTK_CANVAS(track_gtk_canvas)->pixels_per_unit); + } else { + return 0; + } + } + + gulong frame_to_pixel (jack_nframes_t frame) { + return (gulong) rint ((frame / (frames_per_unit * GTK_CANVAS(track_gtk_canvas)->pixels_per_unit))); + } + + /* selection */ + + Selection& get_selection() const { return *selection; } + Selection& get_cut_buffer() const { return *cut_buffer; } + + void play_selection (); + void select_all_in_track (bool add); + void select_all (bool add); + void invert_selection_in_track (); + void invert_selection (); + + /* tempo */ + + void set_show_measures (bool yn); + bool show_measures () const { return _show_measures; } + + /* export */ + + /* these initiate export ... */ + + void export_session(); + void export_selection(); + + /* this is what actually does it */ + + void export_audiofile (ARDOUR::AudioExportSpecification&); + + /* */ + + void add_toplevel_controls (Gtk::Container&); + + void set_zoom_focus (Editing::ZoomFocus); + Editing::ZoomFocus get_zoom_focus () const { return zoom_focus; } + gdouble get_current_zoom () { return frames_per_unit; } + + void temporal_zoom_step (bool coarser); + + /* stuff that AudioTimeAxisView and related classes use */ + + PlaylistSelector& playlist_selector() const; + void route_name_changed (TimeAxisView *); + gdouble frames_per_unit; + jack_nframes_t leftmost_frame; + void clear_playlist (ARDOUR::Playlist&); + + TrackViewList* get_valid_views (TimeAxisView*, ARDOUR::RouteGroup* grp = 0); + + Width editor_mixer_strip_width; + void show_editor_mixer (bool yn); + void set_selected_mixer_strip (TimeAxisView&); + void unselect_strip_in_display (TimeAxisView& tv); + void select_strip_in_display (TimeAxisView& tv); + + /* nudge is initiated by transport controls owned by ARDOUR_UI */ + + void nudge_forward (bool next); + void nudge_backward (bool next); + + /* nudge initiated from context menu */ + + void nudge_forward_capture_offset (); + void nudge_backward_capture_offset (); + + /* playhead/screen stuff */ + + void set_follow_playhead (bool yn); + void toggle_follow_playhead (); + bool follow_playhead() const { return _follow_playhead; } + + /* xfades */ + + void toggle_xfades_active(); + void toggle_xfade_visibility (); + void set_xfade_visibility (bool yn); + bool xfade_visibility() const { return _xfade_visibility; } + + /* redirect shared ops menu. caller must free returned menu */ + + Gtk::Menu* redirect_menu (); + + /* floating windows/transient */ + + void ensure_float (Gtk::Window&); + + void show_window (); + + void scroll_tracks_down_line (); + void scroll_tracks_up_line (); + + bool new_regionviews_display_gain () { return _new_regionviews_show_envelope; } + void prepare_for_cleanup (); + + void reposition_x_origin (jack_nframes_t sample); + + protected: + void map_transport_state (); + void map_position_change (jack_nframes_t); + + void realize_impl(); + void map__impl(); + + private: + + ARDOUR::Session *session; + ARDOUR::AudioEngine& engine; + bool constructed; + + PlaylistSelector* _playlist_selector; + + enum ItemType { + RegionItem, + StreamItem, + PlayheadCursorItem, + EditCursorItem, + MarkerItem, + MarkerBarItem, + RangeMarkerBarItem, + TransportMarkerBarItem, + SelectionItem, + GainControlPointItem, + GainLineItem, + GainAutomationControlPointItem, + GainAutomationLineItem, + PanAutomationControlPointItem, + PanAutomationLineItem, + RedirectAutomationControlPointItem, + RedirectAutomationLineItem, + MeterMarkerItem, + TempoMarkerItem, + MeterBarItem, + TempoBarItem, + AudioRegionViewNameHighlight, + AudioRegionViewName, + StartSelectionTrimItem, + EndSelectionTrimItem, + AutomationTrackItem, + FadeInItem, + FadeInHandleItem, + FadeOutItem, + FadeOutHandleItem, + + /* */ + MarkerViewItem, + MarkerTimeAxisItem, + MarkerViewHandleStartItem, + MarkerViewHandleEndItem, + ImageFrameItem, + ImageFrameTimeAxisItem, + ImageFrameHandleStartItem, + ImageFrameHandleEndItem, + /* */ + + CrossfadeViewItem, + + /* don't remove this */ + + NoItem + }; + + void set_frames_per_unit (double); + void frames_per_unit_modified (); + + Editing::MouseMode mouse_mode; + void mouse_insert (GdkEventButton *); + + void pane_allocation_handler (GtkAllocation*, Gtk::Paned*); + + Gtk::HPaned canvas_region_list_pane; + Gtk::HPaned track_list_canvas_pane; + + Gtk::EventBox meter_base; + Gtk::HBox meter_box; + Gtk::EventBox marker_base; + Gtk::HBox marker_box; + Gtk::VBox scrollers_rulers_markers_box; + + void location_changed (ARDOUR::Location *); + void location_flags_changed (ARDOUR::Location *, void *); + void refresh_location_display (); + void refresh_location_display_s (ARDOUR::Change); + void refresh_location_display_internal (ARDOUR::Locations::LocationList&); + void add_new_location (ARDOUR::Location *); + void location_gone (ARDOUR::Location *); + void remove_marker (GtkCanvasItem*, GdkEvent*); + gint really_remove_marker (ARDOUR::Location* loc); + + uint32_t location_marker_color; + uint32_t location_range_color; + uint32_t location_loop_color; + uint32_t location_punch_color; + uint32_t location_cd_marker_color; + + struct LocationMarkers { + Marker* start; + Marker* end; + + ~LocationMarkers (); + + void hide(); + void show (); + void set_name (const string&); + void set_position (jack_nframes_t start, jack_nframes_t end = 0); + void set_color_rgba (uint32_t); + }; + + LocationMarkers *find_location_markers (ARDOUR::Location *); + ARDOUR::Location* find_location_from_marker (Marker *, bool& is_start); + + typedef map LocationMarkerMap; + LocationMarkerMap location_markers; + + void hide_marker (GtkCanvasItem*, GdkEvent*); + void clear_marker_display (); + void mouse_add_new_marker (jack_nframes_t where); + + TimeAxisView* clicked_trackview; + AudioTimeAxisView* clicked_audio_trackview; + AudioRegionView* clicked_regionview; + AudioRegionView* latest_regionview; + uint32_t clicked_selection; + CrossfadeView* clicked_crossfadeview; + ControlPoint* clicked_control_point; + + void catch_vanishing_audio_regionview (AudioRegionView *); + void set_selected_control_point_from_click (bool add = false, bool with_undo = true, bool no_remove=false); + void set_selected_track_from_click (bool add = false, bool with_undo = true, bool no_remove=false); + void set_selected_regionview_from_click (bool add = false, bool no_track_remove=false); + void set_selected_regionview_from_region_list (ARDOUR::Region& region, bool add = false); + gint set_selected_regionview_from_map_event (GdkEventAny*, StreamView*, ARDOUR::Region*); + void collect_new_region_view (AudioRegionView *); + + Gtk::Menu track_context_menu; + Gtk::Menu track_region_context_menu; + Gtk::Menu track_selection_context_menu; + Gtk::Menu track_crossfade_context_menu; + + Gtk::MenuItem* region_edit_menu_split_item; + Gtk::MenuItem* region_edit_menu_split_multichannel_item; + Gtk::Menu * track_region_edit_playlist_menu; + Gtk::Menu * track_edit_playlist_submenu; + Gtk::Menu * track_selection_edit_playlist_submenu; + + void popup_track_context_menu (int, int, ItemType, bool, jack_nframes_t); + Gtk::Menu* build_track_context_menu (jack_nframes_t); + Gtk::Menu* build_track_bus_context_menu (jack_nframes_t); + Gtk::Menu* build_track_region_context_menu (jack_nframes_t frame); + Gtk::Menu* build_track_crossfade_context_menu (jack_nframes_t); + Gtk::Menu* build_track_selection_context_menu (jack_nframes_t); + void add_dstream_context_items (Gtk::Menu_Helpers::MenuList&); + void add_bus_context_items (Gtk::Menu_Helpers::MenuList&); + void add_region_context_items (StreamView*, ARDOUR::Region*, Gtk::Menu_Helpers::MenuList&); + void add_crossfade_context_items (StreamView*, ARDOUR::Crossfade*, Gtk::Menu_Helpers::MenuList&, bool many); + void add_selection_context_items (Gtk::Menu_Helpers::MenuList&); + + void handle_new_route (ARDOUR::Route&); + void handle_new_route_p (ARDOUR::Route*); + void remove_route (TimeAxisView *); + bool route_removal; + + Gtk::HBox global_hpacker; + Gtk::VBox global_vpacker; + Gtk::VBox vpacker; + + GdkCursor *current_canvas_cursor; + + GtkWidget *track_gtk_canvas; + GtkWidget *time_gtk_canvas; + Gtk::Widget *track_canvas; + Gtk::Widget *time_canvas; + + GtkCanvasItem* first_action_message; + GtkCanvasItem *verbose_canvas_cursor; + bool verbose_cursor_visible; + + void session_control_changed (ARDOUR::Session::ControlType); + void queue_session_control_changed (ARDOUR::Session::ControlType); + + + gint track_canvas_motion (GtkCanvasItem*, GdkEvent*); + void set_verbose_canvas_cursor (string, double x, double y); + void set_verbose_canvas_cursor_text (string); + void show_verbose_canvas_cursor(); + void hide_verbose_canvas_cursor(); + + bool verbose_cursor_on; // so far unused + + void flush_track_canvas (); + void flush_time_canvas (); + + Gtk::EventBox time_canvas_event_box; + Gtk::EventBox track_canvas_event_box; + Gtk::EventBox time_button_event_box; + + GtkCanvasItem *minsec_group; + GtkCanvasItem *bbt_group; + GtkCanvasItem *smpte_group; + GtkCanvasItem *frame_group; + GtkCanvasItem *tempo_group; + GtkCanvasItem *meter_group; + GtkCanvasItem *marker_group; + GtkCanvasItem *range_marker_group; + GtkCanvasItem *transport_marker_group; + + enum { + ruler_metric_smpte = 0, + ruler_metric_bbt = 1, + ruler_metric_frames = 2, + ruler_metric_minsec = 3, + + ruler_time_tempo = 4, + ruler_time_meter = 5, + ruler_time_marker = 6, + ruler_time_range_marker = 7, + ruler_time_transport_marker = 8, + }; + + static GtkCustomMetric ruler_metrics[4]; + bool ruler_shown[9]; + bool no_ruler_shown_update; + + gint ruler_button_press (GdkEventButton*); + gint ruler_button_release (GdkEventButton*); + gint ruler_mouse_motion (GdkEventMotion*); + + gint ruler_pressed_button; + Gtk::Widget * ruler_grabbed_widget; + + void initialize_rulers (); + void update_just_smpte (); + void update_fixed_rulers (); + void update_tempo_based_rulers (); + void popup_ruler_menu (jack_nframes_t where = 0, ItemType type = RegionItem); + void update_ruler_visibility (); + void ruler_toggled (int); + gint ruler_label_button_release (GdkEventButton*); + void store_ruler_visibility (); + void restore_ruler_visibility (); + + static gint _metric_get_smpte (GtkCustomRulerMark **, gulong, gulong, gint); + static gint _metric_get_bbt (GtkCustomRulerMark **, gulong, gulong, gint); + static gint _metric_get_frames (GtkCustomRulerMark **, gulong, gulong, gint); + static gint _metric_get_minsec (GtkCustomRulerMark **, gulong, gulong, gint); + + gint metric_get_smpte (GtkCustomRulerMark **, gulong, gulong, gint); + gint metric_get_bbt (GtkCustomRulerMark **, gulong, gulong, gint); + gint metric_get_frames (GtkCustomRulerMark **, gulong, gulong, gint); + gint metric_get_minsec (GtkCustomRulerMark **, gulong, gulong, gint); + + GtkWidget *_smpte_ruler; + GtkWidget *_bbt_ruler; + GtkWidget *_frames_ruler; + GtkWidget *_minsec_ruler; + Gtk::Widget *smpte_ruler; + Gtk::Widget *bbt_ruler; + Gtk::Widget *frames_ruler; + Gtk::Widget *minsec_ruler; + static Editor *ruler_editor; + + static const double timebar_height; + guint32 visible_timebars; + Gtk::Menu *editor_ruler_menu; + + + GtkCanvasItem *tempo_bar; + GtkCanvasItem *meter_bar; + GtkCanvasItem *marker_bar; + GtkCanvasItem *range_marker_bar; + + GtkCanvasItem *transport_marker_bar; + + + GtkCanvasItem *tempo_line; + GtkCanvasItem *meter_line; + GtkCanvasItem *marker_line; + GtkCanvasItem *range_marker_line; + GtkCanvasItem *transport_marker_line; + + GtkCanvasPoints *tempo_line_points; + GtkCanvasPoints *meter_line_points; + GtkCanvasPoints *marker_line_points; + GtkCanvasPoints *range_marker_line_points; + GtkCanvasPoints *transport_marker_line_points; + + Gtk::Label minsec_label; + Gtk::Label bbt_label; + Gtk::Label smpte_label; + Gtk::Label frame_label; + Gtk::Label tempo_label; + Gtk::Label meter_label; + Gtk::Label mark_label; + Gtk::Label range_mark_label; + Gtk::Label transport_mark_label; + + + Gtk::VBox time_button_vbox; + Gtk::HBox time_button_hbox; + + struct Cursor { + Editor& editor; + GtkCanvasPoints *points; + GtkCanvasItem *canvas_item; + jack_nframes_t current_frame; + GtkSignalFunc callback; + double length; + + Cursor (Editor&, const string& color, GtkSignalFunc callback); + ~Cursor (); + + void set_position (jack_nframes_t); + void set_length (double units); + void set_y_axis (double position); + }; + + friend struct Cursor; /* it needs access to several private + fields. XXX fix me. + */ + + Cursor* playhead_cursor; + Cursor* edit_cursor; + GtkCanvasItem* cursor_group; + + void cursor_to_next_region_point (Cursor*, ARDOUR::RegionPoint); + void cursor_to_previous_region_point (Cursor*, ARDOUR::RegionPoint); + void cursor_to_region_point (Cursor*, ARDOUR::RegionPoint, int32_t dir); + void cursor_to_selection_start (Cursor *); + void cursor_to_selection_end (Cursor *); + + ARDOUR::Region* find_next_region (jack_nframes_t, ARDOUR::RegionPoint, int32_t dir, TrackViewList&, TimeAxisView ** = 0); + + vector region_boundary_cache; + void build_region_boundary_cache (); + + Gtk::VBox trackview_vpacker; + + Gtk::HBox top_hbox; + Gtk::HBox bottom_hbox; + + Gtk::Table edit_packer; + Gtk::Frame edit_frame; + Gtk::VScrollbar edit_vscrollbar; + + /* the horizontal scroller works in a rather different way + than a regular scrollbar, since its used for + zoom control/indication as well. But more importantly, + its different components (slider, left arrow, right arrow) + have to be packed separately into the edit_packer. + */ + + Gtk::HScrollbar edit_hscrollbar; + Gtk::DrawingArea edit_hscroll_slider; + Gtk::Arrow edit_hscroll_left_arrow; + Gtk::Arrow edit_hscroll_right_arrow; + Gtk::EventBox edit_hscroll_left_arrow_event; + Gtk::EventBox edit_hscroll_right_arrow_event; + gint edit_hscroll_slider_width; + gint edit_hscroll_slider_height; + static const gint edit_hscroll_edge_width = 3; + bool edit_hscroll_dragging; + double edit_hscroll_drag_last; + + void hscroll_slider_allocate (GtkAllocation *); + gint hscroll_slider_expose (GdkEventExpose*); + gint hscroll_slider_button_press (GdkEventButton*); + gint hscroll_slider_button_release (GdkEventButton*); + gint hscroll_slider_motion (GdkEventMotion*); + + gint hscroll_trough_expose (GdkEventExpose*); + gint hscroll_trough_button_press (GdkEventButton*); + gint hscroll_trough_button_release (GdkEventButton*); + + void update_hscroller (); + + gint hscroll_left_arrow_button_press (GdkEventButton *); + gint hscroll_left_arrow_button_release (GdkEventButton *); + gint hscroll_right_arrow_button_press (GdkEventButton *); + gint hscroll_right_arrow_button_release (GdkEventButton *); + + guint32 canvas_width; + guint32 canvas_height; + + Gtk::ScrolledWindow track_canvas_scroller; + Gtk::ScrolledWindow time_canvas_scroller; + Gtk::ScrolledWindow edit_controls_scroller; + + gint edit_controls_button_release (GdkEventButton*); + Gtk::Menu *edit_controls_left_menu; + Gtk::Menu *edit_controls_right_menu; + + void track_canvas_scroller_realized (); + void time_canvas_scroller_realized (); + + Gtk::VBox track_canvas_vbox; + Gtk::VBox time_canvas_vbox; + Gtk::VBox edit_controls_vbox; + Gtk::HBox edit_controls_hbox; + + void tie_vertical_scrolling (); + void canvas_horizontally_scrolled (); + void reposition_and_zoom (jack_nframes_t sample, double fpu); + gint deferred_reposition_and_zoom (jack_nframes_t sample, double fpu); + void end_location_changed (ARDOUR::Location*); + bool repos_zoom_queued; + bool no_zoom_repos_update; + bool no_tempo_map_update; + + Gtk::CTree region_list_display; + Gtk::CTree_Helpers::RowList::iterator region_list_hidden_node; + Gtk::Menu *region_list_menu; + vector rl_context_menu_region_items; + Gtk::ScrolledWindow region_list_scroller; + Gtk::Frame region_list_frame; + + gint region_list_display_key_press (GdkEventKey *); + gint region_list_display_key_release (GdkEventKey *); + gint region_list_display_button_press (GdkEventButton *); + gint region_list_display_button_release (GdkEventButton *); + gint region_list_display_enter_notify (GdkEventCrossing *); + gint region_list_display_leave_notify (GdkEventCrossing *); + void region_list_display_selected (gint row, gint col, GdkEvent* ev); + void region_list_display_unselected (gint row, gint col, GdkEvent* ev); + void region_list_column_click (gint); + void region_list_clear (); + void build_region_list_menu (); + + Gtk::CheckMenuItem* toggle_auto_regions_item; + Gtk::CheckMenuItem* toggle_full_region_list_item; + + Gtk::MenuItem* import_audio_item; + Gtk::MenuItem* embed_audio_item; + + bool show_automatic_regions_in_region_list; + Editing::RegionListSortType region_list_sort_type; + + void reset_region_list_sort_direction (bool); + void reset_region_list_sort_type (Editing::RegionListSortType); + + void toggle_full_region_list (); + void toggle_show_auto_regions (); + + static gint _region_list_sorter (GtkCList*, gconstpointer, gconstpointer); + gint region_list_sorter (gconstpointer, gconstpointer); + + /* named selections */ + + Gtk::VPaned region_selection_vpane; + Gtk::CList named_selection_display; + Gtk::ScrolledWindow named_selection_scroller; + + void name_selection(); + void named_selection_name_chosen (); + void create_named_selection (string); + void paste_named_selection (float times); + + void handle_new_named_selection (); + void add_named_selection_to_named_selection_display (ARDOUR::NamedSelection&); + void redisplay_named_selections (); + + gint named_selection_display_button_press (GdkEventButton *ev); + void named_selection_display_selected (gint row, gint col, GdkEvent *ev); + void named_selection_display_unselected (gint row, gint col, GdkEvent *ev); + + /* track views */ + int track_spacing; + TrackViewList track_views; + TimeAxisView *trackview_by_y_position (double ypos); + + static GdkCursor* cross_hair_cursor; + static GdkCursor* trimmer_cursor; + static GdkCursor* selector_cursor; + static GdkCursor* grabber_cursor; + static GdkCursor* zoom_cursor; + static GdkCursor* time_fx_cursor; + static GdkCursor* fader_cursor; + static GdkCursor* speaker_cursor; + static GdkCursor* null_cursor; + static GdkCursor* wait_cursor; + static GdkCursor* timebar_cursor; + + static void build_cursors (); + + SigC::Connection scroll_connection; + jack_nframes_t last_update_frame; + void center_screen (jack_nframes_t); + void center_screen_internal (jack_nframes_t, float); + + void update_current_screen (); + SigC::Connection slower_update_connection; + void update_slower (); + + gint show_track_context_menu (GdkEventButton *); + void hide_track_context_menu (); + + void session_going_away (); + + jack_nframes_t cut_buffer_start; + jack_nframes_t cut_buffer_length; + + gint typed_event (GtkCanvasItem*, GdkEvent*, ItemType); + gint button_press_handler (GtkCanvasItem*, GdkEvent*, ItemType); + gint button_release_handler (GtkCanvasItem*, GdkEvent*, ItemType); + gint motion_handler (GtkCanvasItem*, GdkEvent*, ItemType); + gint enter_handler (GtkCanvasItem*, GdkEvent*, ItemType); + gint leave_handler (GtkCanvasItem*, GdkEvent*, ItemType); + + /* KEYMAP HANDLING */ + + void install_keybindings (); + + int ensure_cursor (jack_nframes_t* pos); + + void fake_handle_new_audio_region (ARDOUR::AudioRegion *); + void handle_new_audio_region (ARDOUR::AudioRegion *); + void fake_handle_audio_region_removed (ARDOUR::AudioRegion *); + void handle_audio_region_removed (ARDOUR::AudioRegion *); + void add_audio_region_to_region_display (ARDOUR::AudioRegion *); + void region_hidden (ARDOUR::Region*); + void redisplay_regions (); + void insert_into_tmp_audio_regionlist(ARDOUR::AudioRegion *); + + list tmp_audio_region_list; + + void cut_copy (Editing::CutCopyOp); + void cut_copy_points (Editing::CutCopyOp); + void cut_copy_regions (Editing::CutCopyOp); + void cut_copy_ranges (Editing::CutCopyOp); + + void mouse_paste (); + void paste_internal (jack_nframes_t position, float times); + + /* EDITING OPERATIONS */ + + void toggle_region_mute (); + void toggle_region_opaque (); + void raise_region (); + void raise_region_to_top (); + void lower_region (); + void lower_region_to_bottom (); + void split_region (); + void split_region_at (jack_nframes_t); + void split_regions_at (jack_nframes_t, AudioRegionSelection&); + void crop_region_to_selection (); + void set_region_sync_from_edit_cursor (); + void remove_region_sync(); + void align_selection (ARDOUR::RegionPoint, jack_nframes_t position); + void align_selection_relative (ARDOUR::RegionPoint point, jack_nframes_t position); + void align_region (ARDOUR::Region&, ARDOUR::RegionPoint point, jack_nframes_t position); + void align_region_internal (ARDOUR::Region&, ARDOUR::RegionPoint point, jack_nframes_t position); + void remove_some_regions (); + void remove_clicked_region (); + void destroy_clicked_region (); + void edit_region (); + void duplicate_some_regions (AudioRegionSelection&, float times); + void duplicate_selection (float times); + void region_fill_selection (); + + void region_fill_track (); + void audition_playlist_region_standalone (ARDOUR::AudioRegion&); + void audition_playlist_region_via_route (ARDOUR::AudioRegion&, ARDOUR::Route&); + void split_multichannel_region(); + void reverse_region (); + void normalize_region (); + void denormalize_region (); + + ARDOUR::Region* region_list_button_region; + void audition_region_from_region_list (); + void remove_region_from_region_list (); + void hide_region_from_region_list (); + void remove_selected_regions_from_region_list (); + + void align (ARDOUR::RegionPoint); + void align_relative (ARDOUR::RegionPoint); + void naturalize (); + + void cut (); + void copy (); + void paste (float times); + + int get_prefix (float&, bool&); + + void keyboard_paste (); + void keyboard_duplicate_region (); + void keyboard_duplicate_selection (); + void keyboard_nudge (); + void keyboard_insert_region_list_selection (); + + void region_from_selection (); + void create_region_from_selection (std::vector&); + + bool region_renamed; + void rename_region (); + void rename_region_finished (bool); + + void play_from_start (); + void play_from_edit_cursor (); + void play_selected_region (); + void audition_selected_region (); + void toggle_loop_playback (); + void loop_selected_region (); + void play_location (ARDOUR::Location&); + void loop_location (ARDOUR::Location&); + + Editing::ZoomFocus zoom_focus; + + void temporal_zoom_selection (); + void temporal_zoom_session (); + void temporal_zoom (gdouble scale); + void temporal_zoom_by_frame (jack_nframes_t start, jack_nframes_t end, string op); + void temporal_zoom_to_frame (bool coarser, jack_nframes_t frame); + + void amplitude_zoom (gdouble scale); + void amplitude_zoom_step (bool in); + + ARDOUR::AudioRegion* region_list_display_drag_region; + char need_wave_cursor; + gint region_list_display_motion (GdkEventMotion*); + + void insert_region_list_drag (ARDOUR::AudioRegion&); + void insert_region_list_selection (float times); + + void insert_sndfile (bool as_tracks); + void embed_audio (); // inserts into region list + int reject_because_rate_differs (string path, SF_INFO& finfo, string action, bool multiple_pending); + + void do_embed_sndfiles (vector paths, bool split); + void embed_sndfile (string path, bool split, bool multiple_files, bool& check_sr); + + void do_insert_sndfile (vector path, bool multi, jack_nframes_t frame); + void insert_paths_as_new_tracks (std::vector paths, bool multi); // inserts files as new tracks + void insert_sndfile_into (string path, bool multi, AudioTimeAxisView* tv, jack_nframes_t& frame, bool prompt=true); + static void* _insert_sndfile_thread (void*); + void* insert_sndfile_thread (void*); + + /* generic interthread progress window */ + + ArdourDialog* interthread_progress_window; + Gtk::Label interthread_progress_label; + Gtk::VBox interthread_progress_vbox; + Gtk::ProgressBar interthread_progress_bar; + Gtk::Button interthread_cancel_button; + Gtk::Label interthread_cancel_label; + SigC::Connection interthread_progress_connection; + void interthread_cancel_clicked (); + void build_interthread_progress_window (); + ARDOUR::InterThreadInfo* current_interthread_info; + + /* import specific info */ + + ARDOUR::Session::import_status import_status; + gint import_progress_timeout (void *); + static void *_import_thread (void *); + void* import_thread (); + void catch_new_audio_region (ARDOUR::AudioRegion*); + ARDOUR::AudioRegion* last_audio_region; + + /* to support this ... */ + + void import_audio (bool as_tracks); + void do_import (vector paths, bool split, bool as_tracks); + + void move_to_start (); + void move_to_end (); + void goto_frame (); + void center_playhead (); + void center_edit_cursor (); + void edit_cursor_backward (); + void edit_cursor_forward (); + void playhead_backward (); + void playhead_forward (); + void scroll_backward (float pages=0.8f); + void scroll_forward (float pages=0.8f); + void scroll_tracks_down (); + void scroll_tracks_up (); + void delete_sample_forward (); + void delete_sample_backward (); + void delete_screen (); + void search_backwards (); + void search_forwards (); + void set_mark (); + void clear_markers (); + void clear_ranges (); + void clear_locations (); + void jump_forward_to_mark (); + void jump_backward_to_mark (); + void cursor_align (bool playhead_to_edit); + + void remove_last_capture (); + + void set_selection_from_range (ARDOUR::Location&); + void set_selection_from_punch (); + void set_selection_from_loop (); + + void add_location_from_selection (); + void set_route_loop_selection (); + + void add_location_from_playhead_cursor (); + + void reverse_selection (); + void edit_envelope (); + + void start_scrolling (); + void stop_scrolling (); + + void keyboard_selection_begin (); + void keyboard_selection_finish (bool add); + bool have_pending_keyboard_selection; + jack_nframes_t pending_keyboard_selection_start; + + ARDOUR::AudioRegion* select_region_for_operation (int dir, TimeAxisView **tv); + void extend_selection_to_end_of_region (bool next); + void extend_selection_to_start_of_region (bool previous); + + Editing::SnapType snap_type; + Editing::SnapMode snap_mode; + double snap_threshold; + + void soundfile_chosen_for_insert (string selection, bool split_channels); + void soundfile_chosen_for_embed (string selection, bool split_channels); + void soundfile_chosen_for_import (string selection, bool split_channels); + + void handle_gui_changes (string, void *); + + void hide_all_tracks (bool with_select); + + void route_list_selected (gint row, gint col, GdkEvent* ev); + void route_list_unselected (gint row, gint col, GdkEvent* ev); + void redisplay_route_list(); + gint route_list_reordered (); + bool ignore_route_list_reorder; + void queue_route_list_reordered (gint row, gint col); + + struct DragInfo { + GtkCanvasItem* item; + void* data; + jack_nframes_t last_frame_position; + int32_t pointer_frame_offset; + jack_nframes_t grab_frame; + jack_nframes_t last_pointer_frame; + jack_nframes_t current_pointer_frame; + double grab_x, grab_y; + double cumulative_x_drag; + double cumulative_y_drag; + double current_pointer_x; + double current_pointer_y; + void (Editor::*motion_callback)(GtkCanvasItem*, GdkEvent*); + void (Editor::*finished_callback)(GtkCanvasItem*, GdkEvent*); + TimeAxisView* last_trackview; + bool x_constrained; + bool copy; + bool was_rolling; + bool first_move; + bool move_threshold_passsed; + bool want_move_threshold; + bool brushing; + ARDOUR::Location* copied_location; + } drag_info; + + struct LineDragInfo { + uint32_t before; + uint32_t after; + }; + + LineDragInfo current_line_drag_info; + + void start_grab (GdkEvent*, GdkCursor* cursor = 0); + bool end_grab (GtkCanvasItem*, GdkEvent*); + + Gtk::Menu fade_context_menu; + void popup_fade_context_menu (int, int, GtkCanvasItem*, ItemType); + + void start_fade_in_grab (GtkCanvasItem*, GdkEvent*); + void start_fade_out_grab (GtkCanvasItem*, GdkEvent*); + void fade_in_drag_motion_callback (GtkCanvasItem*, GdkEvent*); + void fade_out_drag_motion_callback (GtkCanvasItem*, GdkEvent*); + void fade_in_drag_finished_callback (GtkCanvasItem*, GdkEvent*); + void fade_out_drag_finished_callback (GtkCanvasItem*, GdkEvent*); + + std::set motion_frozen_playlists; + void region_drag_motion_callback (GtkCanvasItem*, GdkEvent*); + void region_drag_finished_callback (GtkCanvasItem*, GdkEvent*); + void region_copy_drag_finished_callback (GtkCanvasItem*, GdkEvent*); + + void cursor_drag_motion_callback (GtkCanvasItem*, GdkEvent*); + void cursor_drag_finished_callback (GtkCanvasItem*, GdkEvent*); + void marker_drag_motion_callback (GtkCanvasItem*, GdkEvent*); + void marker_drag_finished_callback (GtkCanvasItem*, GdkEvent*); + void control_point_drag_motion_callback (GtkCanvasItem*, GdkEvent*); + void control_point_drag_finished_callback (GtkCanvasItem*, GdkEvent*); + void line_drag_motion_callback (GtkCanvasItem*, GdkEvent*); + void line_drag_finished_callback (GtkCanvasItem*, GdkEvent*); + + void tempo_marker_drag_motion_callback (GtkCanvasItem*, GdkEvent*); + void tempo_marker_drag_finished_callback (GtkCanvasItem*, GdkEvent*); + void meter_marker_drag_motion_callback (GtkCanvasItem*, GdkEvent*); + void meter_marker_drag_finished_callback (GtkCanvasItem*, GdkEvent*); + + gint mouse_rename_region (GtkCanvasItem*, GdkEvent*); + + void start_region_grab (GtkCanvasItem*, GdkEvent*); + void start_region_copy_grab (GtkCanvasItem*, GdkEvent*); + void start_region_brush_grab (GtkCanvasItem*, GdkEvent*); + void start_selection_grab (GtkCanvasItem*, GdkEvent*); + void start_cursor_grab (GtkCanvasItem*, GdkEvent*); + void start_marker_grab (GtkCanvasItem*, GdkEvent*); + void start_control_point_grab (GtkCanvasItem*, GdkEvent*); + void start_line_grab_from_regionview (GtkCanvasItem*, GdkEvent*); + void start_line_grab_from_line (GtkCanvasItem*, GdkEvent*); + void start_line_grab (AutomationLine *, GdkEvent*); + void start_tempo_marker_grab (GtkCanvasItem*, GdkEvent*); + void start_meter_marker_grab (GtkCanvasItem*, GdkEvent*); + + void region_view_item_click (AudioRegionView&, GdkEventButton*); + + void remove_gain_control_point (GtkCanvasItem*, GdkEvent*); + void remove_control_point (GtkCanvasItem*, GdkEvent*); + + void mouse_brush_insert_region (AudioRegionView*, jack_nframes_t pos); + void brush (jack_nframes_t); + + void show_verbose_time_cursor (jack_nframes_t frame, double offset = 0, double xpos=-1, double ypos=-1); + void show_verbose_duration_cursor (jack_nframes_t start, jack_nframes_t end, double offset = 0, double xpos=-1, double ypos=-1); + + /* static versions of these are public in PublicEditor */ + + gint _canvas_crossfade_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_fade_in_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_fade_in_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_fade_out_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_fade_out_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_region_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_region_view_name_highlight_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_region_view_name_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_stream_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_automation_track_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_zoom_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_selection_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_selection_start_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_selection_end_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_control_point_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_line_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_tempo_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_meter_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_tempo_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_meter_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_range_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_transport_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint _canvas_imageframe_item_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) ; + gint _canvas_imageframe_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) ; + gint _canvas_imageframe_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + gint _canvas_imageframe_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + gint _canvas_marker_time_axis_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + gint _canvas_markerview_item_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + gint _canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + gint _canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + + /* now the real things */ + + gint canvas_crossfade_view_event (GtkCanvasItem* item, GdkEvent* event, CrossfadeView*); + gint canvas_fade_in_event (GtkCanvasItem* item, GdkEvent* event, AudioRegionView*); + gint canvas_fade_in_handle_event (GtkCanvasItem* item, GdkEvent* event, AudioRegionView*); + gint canvas_fade_out_event (GtkCanvasItem* item, GdkEvent* event, AudioRegionView*); + gint canvas_fade_out_handle_event (GtkCanvasItem* item, GdkEvent* event, AudioRegionView*); + gint canvas_region_view_event (GtkCanvasItem* item, GdkEvent* event, AudioRegionView*); + gint canvas_stream_view_event (GtkCanvasItem* item, GdkEvent* event, AudioTimeAxisView*); + gint canvas_automation_track_event (GtkCanvasItem* item, GdkEvent* event, AutomationTimeAxisView*); + gint canvas_marker_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_zoom_rect_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_selection_rect_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_selection_start_trim_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_selection_end_trim_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_control_point_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_line_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_tempo_marker_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_meter_marker_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_tempo_bar_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_meter_bar_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_marker_bar_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_range_marker_bar_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_transport_marker_bar_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_region_view_name_highlight_event (GtkCanvasItem* item, GdkEvent* event); + gint canvas_region_view_name_event (GtkCanvasItem* item, GdkEvent* event); + + /* these are not publically accessible, but we still need the static versions + till we use Gnome::Canvas. + */ + + static gint _canvas_copy_region_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint canvas_copy_region_event (GtkCanvasItem* item, GdkEvent* event); + + static gint _canvas_playhead_cursor_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint canvas_playhead_cursor_event (GtkCanvasItem* item, GdkEvent* event); + + static gint _canvas_edit_cursor_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint canvas_edit_cursor_event (GtkCanvasItem* item, GdkEvent* event); + + static gint _track_canvas_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + gint track_canvas_event (GtkCanvasItem* item, GdkEvent* event); + + gint track_canvas_button_press_event (GdkEventButton *); + gint track_canvas_button_release_event (GdkEventButton *); + + void track_canvas_allocate (GtkAllocation* alloc); + void time_canvas_allocate (GtkAllocation* alloc); + + void set_edit_cursor (GdkEvent* event); + void set_playhead_cursor (GdkEvent* event); + + void kbd_driver (SigC::Slot1, bool use_track_canvas = true, bool use_time_canvas = true, bool can_select = true); + void kbd_set_playhead_cursor (); + void kbd_set_edit_cursor (); + void kbd_split (); + void kbd_align (ARDOUR::RegionPoint); + void kbd_align_relative (ARDOUR::RegionPoint); + void kbd_brush (); + void kbd_audition (); + + void kbd_do_split (GdkEvent*); + void kbd_do_align (GdkEvent*, ARDOUR::RegionPoint); + void kbd_do_align_relative (GdkEvent*, ARDOUR::RegionPoint); + void kbd_do_brush (GdkEvent*); + void kbd_do_audition (GdkEvent*); + + void fake_handle_new_duration (); + void handle_new_duration (); + void initialize_canvas (); + void reset_scrolling_region (GtkAllocation* alloc = 0); + void scroll_canvas (); + + /* sub-event loop handling */ + + int32_t sub_event_loop_status; + void run_sub_event_loop (); + void finish_sub_event_loop (int status); + gint finish_sub_event_loop_on_delete (GdkEventAny*, int32_t status); + + /* display control */ + + bool _show_measures; + bool _show_waveforms; + bool _follow_playhead; + bool _show_waveforms_recording; + + void add_bbt_marks (ARDOUR::TempoMap::BBTPointList&); + + ARDOUR::TempoMap::BBTPointList *current_bbt_points; + + typedef vector TimeLineList; + TimeLineList free_measure_lines; + TimeLineList used_measure_lines; + + GtkCanvasItem* time_line_group; + GtkCanvasItem* get_time_line (); + void hide_measures (); + void draw_measures (); + void draw_time_bars (); + + void new_tempo_section (); + + void mouse_add_new_tempo_event (jack_nframes_t where); + void mouse_add_new_meter_event (jack_nframes_t where); + + void remove_tempo_marker (GtkCanvasItem*); + void remove_meter_marker (GtkCanvasItem*); + gint real_remove_tempo_marker (ARDOUR::TempoSection*); + gint real_remove_meter_marker (ARDOUR::MeterSection*); + + void edit_tempo_section (ARDOUR::TempoSection*); + void edit_meter_section (ARDOUR::MeterSection*); + void edit_tempo_marker (GtkCanvasItem*); + void edit_meter_marker (GtkCanvasItem*); + + void marker_menu_edit (); + void marker_menu_remove (); + void marker_menu_rename (); + void marker_menu_hide (); + void marker_menu_loop_range (); + void marker_menu_play_from (); + void marker_menu_set_playhead (); + void marker_menu_set_from_playhead (); + void marker_menu_set_from_selection (); + void new_transport_marker_menu_set_loop (); + void new_transport_marker_menu_set_punch (); + void update_loop_range_view (bool visibility=false); + void update_punch_range_view (bool visibility=false); + gint new_transport_marker_menu_popdown (GdkEventAny*); + void marker_context_menu (GdkEventButton*, GtkCanvasItem*); + void tm_marker_context_menu (GdkEventButton*, GtkCanvasItem*); + void transport_marker_context_menu (GdkEventButton*, GtkCanvasItem*); + void new_transport_marker_context_menu (GdkEventButton*, GtkCanvasItem*); + void build_marker_menu (); + void build_tm_marker_menu (); + void build_transport_marker_menu (); + void build_new_transport_marker_menu (); + + Gtk::Menu* tm_marker_menu; + Gtk::Menu* marker_menu; + Gtk::Menu* transport_marker_menu; + Gtk::Menu* new_transport_marker_menu; + GtkCanvasItem* marker_menu_item; + + typedef list Marks; + Marks metric_marks; + + void remove_metric_marks (); + void draw_metric_marks (const ARDOUR::Metrics& metrics); + + void tempo_map_changed (ARDOUR::Change); + void redisplay_tempo (); + + void snap_to (jack_nframes_t& first, int32_t direction = 0, bool for_mark = false); + uint32_t bbt_beat_subdivision; + + /* toolbar */ + + Gtk::ToggleButton editor_mixer_button; + + void editor_mixer_button_toggled (); + + AudioClock selection_start_clock; + Gtk::Label selection_start_clock_label; + AudioClock selection_end_clock; + Gtk::Label selection_end_clock_label; + AudioClock edit_cursor_clock; + Gtk::Label edit_cursor_clock_label; + AudioClock zoom_range_clock; + Gtk::Button zoom_in_button; + Gtk::Button zoom_out_button; + Gtk::Button zoom_out_full_button; + Gtk::Button zoom_onetoone_button; + + Gtk::VBox toolbar_clock_vbox; + Gtk::VBox toolbar_selection_clock_vbox; + Gtk::Table toolbar_selection_clock_table; + Gtk::Label toolbar_selection_cursor_label; + + Gtk::Table mouse_mode_button_table; + Gtkmmext::TearOff* mouse_mode_tearoff; + Gtk::ToggleButton mouse_select_button; + Gtk::ToggleButton mouse_move_button; + Gtk::ToggleButton mouse_gain_button; + Gtk::ToggleButton mouse_zoom_button; + Gtk::ToggleButton mouse_timefx_button; + Gtk::ToggleButton mouse_audition_button; + GroupedButtons *mouse_mode_button_set; + void mouse_mode_toggled (Editing::MouseMode m); + bool ignore_mouse_mode_toggle; + + gint mouse_select_button_release (GdkEventButton*); + + Gtk::VBox automation_box; + Gtk::Button automation_mode_button; + Gtk::ToggleButton global_automation_button; + + Gtk::Combo edit_mode_selector; + Gtk::Label edit_mode_label; + Gtk::VBox edit_mode_box; + + gint edit_mode_selection_done (GdkEventAny*); + + Gtk::Combo snap_type_selector; + Gtk::Label snap_type_label; + Gtk::VBox snap_type_box; + + gint snap_type_selection_done (GdkEventAny*); + + Gtk::Combo snap_mode_selector; + Gtk::Label snap_mode_label; + Gtk::VBox snap_mode_box; + + gint snap_mode_selection_done (GdkEventAny*); + + Gtk::Combo zoom_focus_selector; + Gtk::Label zoom_focus_label; + Gtk::VBox zoom_focus_box; + + gint zoom_focus_selection_done (GdkEventAny*); + + Gtk::Label zoom_indicator_label; + Gtk::HBox zoom_indicator_box; + Gtk::VBox zoom_indicator_vbox; + + void update_zoom_indicator (); + void zoom_adjustment_changed(); + + void edit_cursor_clock_changed(); + + void setup_toolbar (); + + Gtkmmext::TearOff* tools_tearoff; + Gtk::HBox toolbar_hbox; + Gtk::EventBox toolbar_base; + Gtk::Frame toolbar_frame; + + /* selection process */ + + Selection* selection; + Selection* cut_buffer; + + void time_selection_changed (); + void track_selection_changed (); + void region_selection_changed (); + void point_selection_changed (); + void audio_track_selection_changed (); + void line_selection_changed (); + + enum SelectionOp { + CreateSelection, + SelectionStartTrim, + SelectionEndTrim, + SelectionMove + } selection_op; + + void start_selection_op (GtkCanvasItem* item, GdkEvent* event, SelectionOp); + void drag_selection (GtkCanvasItem* item, GdkEvent* event); + void end_selection_op (GtkCanvasItem* item, GdkEvent* event); + void cancel_selection (); + + void region_selection_op (void (ARDOUR::Region::*pmf)(void)); + void region_selection_op (void (ARDOUR::Region::*pmf)(void*), void*); + void region_selection_op (void (ARDOUR::Region::*pmf)(bool), bool); + + bool audio_region_selection_covers (jack_nframes_t where); + + Gtk::VPaned route_group_vpane; + Gtk::Frame route_list_frame; + Gtk::Frame edit_group_list_frame; + + /* transport range select process */ + enum RangeMarkerOp { + CreateRangeMarker, + CreateTransportMarker + } range_marker_op; + + void start_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event, RangeMarkerOp); + void drag_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event); + void end_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event); + + + GtkCanvasItem *range_bar_drag_rect; + GtkCanvasItem *transport_bar_drag_rect; + GtkCanvasItem *marker_drag_line; + GtkCanvasPoints *marker_drag_line_points; + GtkCanvasItem *range_marker_drag_rect; + + void update_marker_drag_item (ARDOUR::Location *); + + GtkCanvasItem *transport_bar_range_rect; + GtkCanvasItem *transport_bar_preroll_rect; + GtkCanvasItem *transport_bar_postroll_rect; + GtkCanvasItem *transport_loop_range_rect; + GtkCanvasItem *transport_punch_range_rect; + GtkCanvasItem *transport_punchin_line; + GtkCanvasItem *transport_punchout_line; + GtkCanvasItem *transport_preroll_rect; + GtkCanvasItem *transport_postroll_rect; + + ARDOUR::Location* transport_loop_location(); + ARDOUR::Location* transport_punch_location(); + + ARDOUR::Location *temp_location; + + /* object rubberband select process */ + + void start_rubberband_select (GtkCanvasItem* item, GdkEvent* event); + void drag_rubberband_select (GtkCanvasItem* item, GdkEvent* event); + void end_rubberband_select (GtkCanvasItem* item, GdkEvent* event); + + bool select_all_within (jack_nframes_t start, jack_nframes_t end, gdouble topy, gdouble boty, bool add); + + GtkCanvasItem *rubberband_rect; + + /* mouse zoom process */ + + void start_mouse_zoom (GtkCanvasItem* item, GdkEvent* event); + void drag_mouse_zoom (GtkCanvasItem* item, GdkEvent* event); + void end_mouse_zoom (GtkCanvasItem* item, GdkEvent* event); + + GtkCanvasItem *zoom_rect; + void reposition_zoom_rect (jack_nframes_t start, jack_nframes_t end); + + /* diskstream/route display management */ + + Gtk::CList route_list; + Gtk::ScrolledWindow route_list_scroller; + Gtk::Menu *route_list_menu; + + void route_list_column_click (gint); + void build_route_list_menu (); + void select_all_routes (); + void unselect_all_routes (); + void select_all_audiotracks (); + void unselect_all_audiotracks (); + void select_all_audiobus (); + void unselect_all_audiobus (); + + /* edit group management */ + + Gtk::Button edit_group_list_button; + Gtk::Label edit_group_list_button_label; + Gtk::CList edit_group_list; + Gtk::ScrolledWindow edit_group_list_scroller; + Gtk::Menu *edit_group_list_menu; + Gtk::VBox edit_group_vbox; + + + void edit_group_list_column_click (gint); + void build_edit_group_list_menu (); + void select_all_edit_groups (); + void unselect_all_edit_groups (); + void new_edit_group (); + void edit_group_list_button_clicked (); + gint edit_group_list_button_press_event (GdkEventButton* ev); + void edit_group_selected (gint row, gint col, GdkEvent* ev); + void edit_group_unselected (gint row, gint col, GdkEvent* ev); + void fake_add_edit_group (ARDOUR::RouteGroup* group); + void add_edit_group (ARDOUR::RouteGroup* group); + void group_flags_changed (void*, ARDOUR::RouteGroup*); + + Gtk::VBox list_vpacker; + + static GdkPixmap* check_pixmap; + static GdkBitmap* check_mask; + static GdkPixmap* empty_pixmap; + static GdkBitmap* empty_mask; + + /* autoscrolling */ + + int autoscroll_timeout_tag; + int autoscroll_direction; + uint32_t autoscroll_cnt; + jack_nframes_t autoscroll_distance; + + static gint _autoscroll_canvas (void *); + gint autoscroll_canvas (); + void start_canvas_autoscroll (int direction); + void stop_canvas_autoscroll (); + void maybe_autoscroll (GdkEvent*); + + /* trimming */ + enum TrimOp { + StartTrim, + EndTrim, + ContentsTrim, + } trim_op; + + void start_trim (GtkCanvasItem*, GdkEvent*); + void point_trim (GdkEvent*); + void trim_motion_callback (GtkCanvasItem*, GdkEvent*); + void single_contents_trim (AudioRegionView&, jack_nframes_t, bool, bool, bool); + void single_start_trim (AudioRegionView&, jack_nframes_t, bool, bool); + void single_end_trim (AudioRegionView&, jack_nframes_t, bool, bool); + + void trim_finished_callback (GtkCanvasItem*, GdkEvent*); + void thaw_region_after_trim (AudioRegionView& rv); + + void trim_region_to_edit_cursor (); + void trim_region_from_edit_cursor (); + + bool show_gain_after_trim; + + /* Drag-n-Drop */ + + int convert_drop_to_paths (std::vector& paths, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time); + + void track_canvas_drag_data_received (GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time); + + void region_list_display_drag_data_received (GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time); + + /* audio export */ + + ExportDialog *export_dialog; + void export_range (jack_nframes_t start, jack_nframes_t end); + + int write_region_selection(AudioRegionSelection&); + bool write_region (string path, ARDOUR::AudioRegion&); + void export_region (); + void write_a_region (); + void bounce_region_selection (); + void bounce_range_selection (); + void external_edit_region (); + + int write_audio_selection (TimeSelection&); + bool write_audio_range (ARDOUR::Playlist&, uint32_t channels, list&); + + void write_selection (); + + /* history */ + + UndoAction get_memento() const; + + void begin_reversible_command (string cmd_name); + void commit_reversible_command (); + + /* visual history */ + + UndoHistory visual_history; + UndoCommand current_visual_command; + + void begin_reversible_visual_command (string cmd_name); + void commit_reversible_visual_command (); + + void update_title (); + void update_title_s (string snapshot_name); + + struct State { + Selection* selection; + double frames_per_unit; + + State(); + ~State(); + }; + + void store_state (State&) const; + void restore_state (State *); + + void instant_save (); + + ARDOUR::AudioRegion* last_audition_region; + + /* freeze operations */ + + ARDOUR::InterThreadInfo freeze_status; + gint freeze_progress_timeout (void *); + static void* _freeze_thread (void*); + void* freeze_thread (); + + void freeze_route (); + void unfreeze_route (); + + /* edit-group solo + mute */ + + void set_edit_group_solo (ARDOUR::Route&, bool); + void set_edit_group_mute (ARDOUR::Route&, bool); + + /* duplication */ + + void duplicate_dialog (bool for_region); + + /* edit menu */ + + Gtk::Menu* edit_menu; + void edit_menu_map_handler (); + + jack_nframes_t event_frame (GdkEvent*, double* px = 0, double* py = 0); + + void time_fx_motion (GtkCanvasItem*, GdkEvent*); + void start_time_fx (GtkCanvasItem*, GdkEvent*); + void end_time_fx (GtkCanvasItem*, GdkEvent*); + + struct TimeStretchDialog : public ArdourDialog { + ARDOUR::Session::TimeStretchRequest request; + Editor& editor; + AudioRegionSelection regions; + Gtk::ProgressBar progress_bar; + Gtk::ToggleButton quick_button; + Gtk::ToggleButton antialias_button; + Gtk::Button cancel_button; + Gtk::Button action_button; + Gtk::HBox lower_button_box; + Gtk::HBox upper_button_box; + Gtk::VBox packer; + int status; + + TimeStretchDialog (Editor& e); + + gint update_progress (); + SigC::Connection first_cancel; + SigC::Connection first_delete; + void cancel_timestretch_in_progress (); + gint delete_timestretch_in_progress (GdkEventAny*); + }; + + /* "whats mine is yours" */ + + friend class TimeStretchDialog; + + TimeStretchDialog* current_timestretch; + + static void* timestretch_thread (void *arg); + int run_timestretch (AudioRegionSelection&, float fraction); + void do_timestretch (TimeStretchDialog&); + + /* editor-mixer strip */ + + MixerStrip *current_mixer_strip; + Gtk::VBox current_mixer_strip_vbox; + void cms_deleted (); + void current_mixer_strip_hidden (); + void current_mixer_strip_removed (); + + void detach_tearoff (Gtk::Box* b, Gtk::Widget* w); + void reattach_tearoff (Gtk::Box* b, Gtk::Widget* w, int32_t n); + + /* nudging tracks */ + + void nudge_track (bool use_edit_cursor, bool forwards); + + /* xfades */ + + bool _xfade_visibility; + + /* */ + void handle_new_imageframe_time_axis_view(std::string track_name, void* src) ; + void handle_new_imageframe_marker_time_axis_view(std::string track_name, TimeAxisView* marked_track) ; + + void start_imageframe_grab(GtkCanvasItem*, GdkEvent*) ; + void start_markerview_grab(GtkCanvasItem*, GdkEvent*) ; + + void imageframe_drag_motion_callback(GtkCanvasItem*, GdkEvent*) ; + void markerview_drag_motion_callback(GtkCanvasItem*, GdkEvent*) ; + void timeaxis_item_drag_finished_callback(GtkCanvasItem*, GdkEvent*) ; + + gint canvas_imageframe_item_view_event(GtkCanvasItem* item, GdkEvent* event, ImageFrameView* ifv); + gint canvas_imageframe_view_event(GtkCanvasItem* item, GdkEvent* event, ImageFrameTimeAxis* ifta); + gint canvas_imageframe_start_handle_event(GtkCanvasItem* item, GdkEvent* event, ImageFrameView* ifv); + gint canvas_imageframe_end_handle_event(GtkCanvasItem* item, GdkEvent* event, ImageFrameView* ifv); + + gint canvas_marker_time_axis_view_event(GtkCanvasItem* item, GdkEvent* event, MarkerTimeAxis* mta); + gint canvas_markerview_item_view_event(GtkCanvasItem* item, GdkEvent* event, MarkerView* mv); + gint canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, MarkerView* mv); + gint canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, MarkerView* mv); + + void imageframe_start_handle_op(GtkCanvasItem* item, GdkEvent* event) ; + void imageframe_end_handle_op(GtkCanvasItem* item, GdkEvent* event) ; + void imageframe_start_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event) ; + void imageframe_start_handle_end_trim(GtkCanvasItem* item, GdkEvent* event) ; + void imageframe_end_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event) ; + void imageframe_end_handle_end_trim(GtkCanvasItem* item, GdkEvent* event) ; + + void markerview_item_start_handle_op(GtkCanvasItem* item, GdkEvent* event) ; + void markerview_item_end_handle_op(GtkCanvasItem* item, GdkEvent* event) ; + void markerview_start_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event) ; + void markerview_start_handle_end_trim(GtkCanvasItem* item, GdkEvent* event) ; + void markerview_end_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event) ; + void markerview_end_handle_end_trim(GtkCanvasItem* item, GdkEvent* event) ; + + void popup_imageframe_edit_menu(int button, int32_t time, GtkCanvasItem* ifv, bool with_frame) ; + void popup_marker_time_axis_edit_menu(int button, int32_t time, GtkCanvasItem* ifv, bool with_frame) ; + + ImageFrameSocketHandler* image_socket_listener ; + /* */ + + void toggle_xfade_active (ARDOUR::Crossfade*); + void toggle_xfade_length (ARDOUR::Crossfade*); + void edit_xfade (ARDOUR::Crossfade*); + void remove_xfade (); + void xfade_edit_left_region (); + void xfade_edit_right_region (); + + static const int32_t default_width = 995; + static const int32_t default_height = 765; + + /* nudge */ + + Gtk::Button nudge_forward_button; + Gtk::Button nudge_backward_button; + Gtk::HBox nudge_hbox; + Gtk::VBox nudge_vbox; + Gtk::Label nudge_label; + AudioClock nudge_clock; + + jack_nframes_t get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next); + + /* audio filters */ + + void apply_filter (ARDOUR::AudioFilter&, string cmd); + + /* handling cleanup */ + + int playlist_deletion_dialog (ARDOUR::Playlist*); + + vector session_connections; + + /* tracking step changes of track height */ + + TimeAxisView* current_stepping_trackview; + struct timeval last_track_height_step_timestamp; + gint track_height_step_timeout(); + SigC::Connection step_timeout; + + TimeAxisView* entered_track; + AudioRegionView* entered_regionview; + bool clear_entered_track; + gint left_track_canvas (GdkEventCrossing*); + void set_entered_track (TimeAxisView*); + void set_entered_regionview (AudioRegionView*); + gint left_automation_track (); + + bool _new_regionviews_show_envelope; + + void toggle_gain_envelope_visibility (); + void toggle_gain_envelope_active (); + + typedef map ColorStyleMap; + void init_colormap (); +}; + +#endif /* __ardour_editor_h__ */ diff --git a/gtk2_ardour/editor_audiotrack.cc b/gtk2_ardour/editor_audiotrack.cc new file mode 100644 index 0000000000..b9ae734bde --- /dev/null +++ b/gtk2_ardour/editor_audiotrack.cc @@ -0,0 +1,65 @@ +#include +#include + +#include "editor.h" +#include "editing.h" +#include "audio_time_axis.h" +#include "regionview.h" +#include "selection.h" + +using namespace ARDOUR; + +void +Editor::set_route_loop_selection () +{ + if (session == 0 || selection->time.empty()) { + return; + } + + jack_nframes_t start = selection->time[clicked_selection].start; + jack_nframes_t end = selection->time[clicked_selection].end; + + Location* loc = transport_loop_location(); + + if (loc) { + + loc->set (start, end); + + // enable looping, reposition and start rolling + session->request_auto_loop (true); + session->request_locate (loc->start(), true); + } + +} + +void +Editor::set_show_waveforms (bool yn) +{ + AudioTimeAxisView* atv; + + if (_show_waveforms != yn) { + _show_waveforms = yn; + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + if ((atv = dynamic_cast(*i)) != 0) { + atv->set_show_waveforms (yn); + } + } + DisplayControlChanged (Editing::ShowWaveforms); + } +} + +void +Editor::set_show_waveforms_recording (bool yn) +{ + AudioTimeAxisView* atv; + + if (_show_waveforms_recording != yn) { + _show_waveforms_recording = yn; + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + if ((atv = dynamic_cast(*i)) != 0) { + atv->set_show_waveforms_recording (yn); + } + } + DisplayControlChanged (Editing::ShowWaveformsRecording); + } +} diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc new file mode 100644 index 0000000000..060b7d4842 --- /dev/null +++ b/gtk2_ardour/editor_canvas_events.cc @@ -0,0 +1,999 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include + +#include +#include + +#include "editor.h" +#include "public_editor.h" +#include "regionview.h" +#include "streamview.h" +#include "crossfade_view.h" +#include "audio_time_axis.h" +#include "region_gain_line.h" +#include "automation_gain_line.h" +#include "automation_pan_line.h" +#include "automation_time_axis.h" +#include "redirect_automation_line.h" + +#include "i18n.h" + +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; + +gint +Editor::_canvas_copy_region_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + Editor* editor = (Editor*)data; + return editor->canvas_copy_region_event (item, event); +} + +gint +Editor::_canvas_crossfade_view_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + CrossfadeView* xfv = static_cast (data); + Editor* editor = dynamic_cast(&xfv->get_time_axis_view().editor); + return editor->canvas_crossfade_view_event (item, event, xfv); +} + +gint +Editor::_canvas_fade_in_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + AudioRegionView* rv = static_cast (data); + Editor* editor = dynamic_cast(&rv->get_time_axis_view().editor); + return editor->canvas_fade_in_event (item, event, rv); +} + +gint +Editor::_canvas_fade_in_handle_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + AudioRegionView* rv = static_cast (data); + Editor* editor = dynamic_cast(&rv->get_time_axis_view().editor); + return editor->canvas_fade_in_handle_event (item, event, rv); +} + +gint +Editor::_canvas_fade_out_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + AudioRegionView* rv = static_cast (data); + Editor* editor = dynamic_cast(&rv->get_time_axis_view().editor); + return editor->canvas_fade_out_event (item, event, rv); +} + +gint +Editor::_canvas_fade_out_handle_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + AudioRegionView* rv = static_cast (data); + Editor* editor = dynamic_cast(&rv->get_time_axis_view().editor); + return editor->canvas_fade_out_handle_event (item, event, rv); +} + +gint +Editor::_canvas_region_view_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + AudioRegionView *rv = reinterpret_cast(data); + Editor* editor = dynamic_cast(&rv->get_time_axis_view().editor); + + return editor->canvas_region_view_event (item, event, rv); +} + +gint +Editor::_canvas_region_view_name_highlight_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + AudioRegionView *rv = reinterpret_cast (data); + Editor* editor = dynamic_cast(&rv->get_time_axis_view().editor); + + return editor->canvas_region_view_name_highlight_event (item, event); +} + +gint +Editor::_canvas_region_view_name_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + AudioRegionView *rv = reinterpret_cast (data); + Editor* editor = dynamic_cast(&rv->get_time_axis_view().editor); + + return editor->canvas_region_view_name_event (item, event); +} + +gint +Editor::_canvas_stream_view_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + /* note that stream views are by definition audio track views */ + + AudioTimeAxisView *tv = (AudioTimeAxisView *) data; + Editor* editor = dynamic_cast(&tv->editor); + + return editor->canvas_stream_view_event (item, event, tv); +} + +gint +Editor::_canvas_automation_track_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + AutomationTimeAxisView* atv = (AutomationTimeAxisView*) data; + Editor* editor = dynamic_cast(&atv->editor); + + return editor->canvas_automation_track_event (item, event, atv); +} + +gint +Editor::_canvas_control_point_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + ControlPoint *cp = reinterpret_cast(data); + Editor* editor = dynamic_cast(&cp->line.trackview.editor); + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_control_point = cp; + clicked_trackview = &cp->line.trackview; + clicked_audio_trackview = dynamic_cast(clicked_trackview); + clicked_regionview = 0; + break; + + default: + break; + } + + return editor->canvas_control_point_event (item, event); +} + +gint +Editor::_canvas_line_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + AutomationLine *line = reinterpret_cast (data); + Editor* editor = dynamic_cast(&line->trackview.editor); + + return editor->canvas_line_event (item, event); +} + +gint +Editor::_canvas_tempo_marker_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + Editor* editor = dynamic_cast((PublicEditor*) data); + return editor->canvas_tempo_marker_event (item, event); +} + +gint +Editor::_canvas_meter_marker_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + Editor* editor = dynamic_cast((PublicEditor *) data); + return editor->canvas_meter_marker_event (item, event); +} + +gint +Editor::_canvas_tempo_bar_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + /* XXX NO CAST */ + Editor* editor = (Editor*) data; + return editor->canvas_tempo_bar_event (item, event); +} + +gint +Editor::_canvas_meter_bar_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + /* XXX NO CAST */ + Editor* editor = (Editor*) data; + return editor->canvas_meter_bar_event (item, event); +} + +gint +Editor::_canvas_marker_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + Editor* editor = dynamic_cast((PublicEditor*) data); + return editor->canvas_marker_event (item, event); +} + +gint +Editor::_canvas_marker_bar_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + /* NO CAST */ + Editor* editor = (Editor*) data; + return editor->canvas_marker_bar_event (item, event); +} + +gint +Editor::_canvas_range_marker_bar_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + /* NO CAST */ + Editor* editor = (Editor*) data; + return editor->canvas_range_marker_bar_event (item, event); +} + +gint +Editor::_canvas_transport_marker_bar_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + /* NO CAST */ + Editor* editor = (Editor*) data; + return editor->canvas_transport_marker_bar_event (item, event); +} + +gint +Editor::_canvas_playhead_cursor_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + /* NO CAST */ + Editor* editor = (Editor*) data; + return editor->canvas_playhead_cursor_event (item, event); +} + +gint +Editor::_canvas_edit_cursor_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + /* NO CAST */ + Editor* editor = (Editor*) data; + return editor->canvas_edit_cursor_event (item, event); +} + +gint +Editor::_canvas_zoom_rect_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + Editor* editor = dynamic_cast((PublicEditor*) data); + return editor->canvas_zoom_rect_event (item, event); +} + +gint +Editor::_canvas_selection_rect_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + Editor* editor = dynamic_cast((PublicEditor*) data); + return editor->canvas_selection_rect_event (item, event); +} + +gint +Editor::_canvas_selection_start_trim_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + Editor* editor = dynamic_cast((PublicEditor*) data); + return editor->canvas_selection_start_trim_event (item, event); +} + +gint +Editor::_canvas_selection_end_trim_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + Editor* editor = dynamic_cast((PublicEditor*) data); + return editor->canvas_selection_end_trim_event (item, event); +} + +gint +Editor::_track_canvas_event (GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + /* NO CAST */ + + Editor* editor = (Editor*) data; + return editor->track_canvas_event (item, event); +} + +/********** END OF.TATIC EVENT HANDLERS */ + +gint +Editor::track_canvas_event (GtkCanvasItem *item, GdkEvent *event) +{ + gint x, y; + + switch (event->type) { + case GDK_MOTION_NOTIFY: + /* keep those motion events coming */ + track_canvas->get_pointer (x, y); + return track_canvas_motion (item, event); + + case GDK_BUTTON_RELEASE: + switch (event->button.button) { + case 4: + case 5: + button_release_handler (item, event, NoItem); + break; + } + break; + + default: + break; + } + + return FALSE; +} + +gint +Editor::track_canvas_motion (GtkCanvasItem *item, GdkEvent *ev) +{ + if (verbose_cursor_visible) { + gtk_canvas_item_set (verbose_canvas_cursor, + "x", ev->motion.x + 20, + "y", ev->motion.y + 20, + NULL); + } + return FALSE; +} + +gint +Editor::typed_event (GtkCanvasItem *item, GdkEvent *event, ItemType type) +{ + gint ret = FALSE; + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + ret = button_press_handler (item, event, type); + break; + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, type); + break; + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, type); + break; + + case GDK_ENTER_NOTIFY: + ret = enter_handler (item, event, type); + break; + + case GDK_LEAVE_NOTIFY: + ret = leave_handler (item, event, type); + break; + + default: + break; + } + + return ret; +} + +gint +Editor::canvas_region_view_event (GtkCanvasItem *item, GdkEvent *event, AudioRegionView *rv) +{ + gint ret = FALSE; + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_regionview = rv; + clicked_control_point = 0; + clicked_trackview = &rv->get_time_axis_view(); + clicked_audio_trackview = dynamic_cast(clicked_trackview); + ret = button_press_handler (item, event, RegionItem); + break; + + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, RegionItem); + break; + + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, RegionItem); + break; + + case GDK_ENTER_NOTIFY: + set_entered_regionview (rv); + break; + + case GDK_LEAVE_NOTIFY: + set_entered_regionview (0); + break; + + default: + break; + } + + return ret; +} + +gint +Editor::canvas_stream_view_event (GtkCanvasItem *item, GdkEvent *event, AudioTimeAxisView *tv) +{ + gint ret = FALSE; + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_regionview = 0; + clicked_control_point = 0; + clicked_trackview = tv; + clicked_audio_trackview = tv; + ret = button_press_handler (item, event, StreamItem); + break; + + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, StreamItem); + break; + + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, StreamItem); + break; + + case GDK_ENTER_NOTIFY: + break; + + default: + break; + } + + return ret; +} + + + +gint +Editor::canvas_automation_track_event (GtkCanvasItem *item, GdkEvent *event, AutomationTimeAxisView *atv) +{ + gint ret = FALSE; + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_regionview = 0; + clicked_control_point = 0; + clicked_trackview = atv; + clicked_audio_trackview = 0; + ret = button_press_handler (item, event, AutomationTrackItem); + break; + + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, AutomationTrackItem); + break; + + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, AutomationTrackItem); + break; + + case GDK_ENTER_NOTIFY: + ret = enter_handler (item, event, AutomationTrackItem); + break; + + case GDK_LEAVE_NOTIFY: + ret = leave_handler (item, event, AutomationTrackItem); + break; + + default: + break; + } + + return ret; +} + +gint +Editor::canvas_fade_in_event (GtkCanvasItem *item, GdkEvent *event, AudioRegionView *rv) +{ + /* we handle only button 3 press/release events */ + + switch (event->type) { + case GDK_BUTTON_PRESS: + clicked_regionview = rv; + clicked_control_point = 0; + clicked_trackview = &rv->get_time_axis_view(); + clicked_audio_trackview = dynamic_cast(clicked_trackview); + if (event->button.button == 3) { + return button_press_handler (item, event, FadeInItem); + } + break; + + case GDK_BUTTON_RELEASE: + if (event->button.button == 3) { + return button_release_handler (item, event, FadeInItem); + } + break; + + default: + break; + + } + + /* proxy for the regionview */ + + return canvas_region_view_event (rv->get_canvas_group(), event, rv); +} + +gint +Editor::canvas_fade_in_handle_event (GtkCanvasItem *item, GdkEvent *event, AudioRegionView *rv) +{ + gint ret = FALSE; + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_regionview = rv; + clicked_control_point = 0; + clicked_trackview = &rv->get_time_axis_view(); + clicked_audio_trackview = dynamic_cast(clicked_trackview); + ret = button_press_handler (item, event, FadeInHandleItem); + break; + + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, FadeInHandleItem); + break; + + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, FadeInHandleItem); + break; + + case GDK_ENTER_NOTIFY: + ret = enter_handler (item, event, FadeInHandleItem); + break; + + case GDK_LEAVE_NOTIFY: + ret = leave_handler (item, event, FadeInHandleItem); + break; + + default: + break; + } + + return ret; +} + +gint +Editor::canvas_fade_out_event (GtkCanvasItem *item, GdkEvent *event, AudioRegionView *rv) +{ + /* we handle only button 3 press/release events */ + + switch (event->type) { + case GDK_BUTTON_PRESS: + clicked_regionview = rv; + clicked_control_point = 0; + clicked_trackview = &rv->get_time_axis_view(); + clicked_audio_trackview = dynamic_cast(clicked_trackview); + if (event->button.button == 3) { + return button_press_handler (item, event, FadeOutItem); + } + break; + + case GDK_BUTTON_RELEASE: + if (event->button.button == 3) { + return button_release_handler (item, event, FadeOutItem); + } + break; + + default: + break; + + } + + /* proxy for the regionview */ + + return canvas_region_view_event (rv->get_canvas_group(), event, rv); +} + +gint +Editor::canvas_fade_out_handle_event (GtkCanvasItem *item, GdkEvent *event, AudioRegionView *rv) +{ + gint ret = FALSE; + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_regionview = rv; + clicked_control_point = 0; + clicked_trackview = &rv->get_time_axis_view(); + clicked_audio_trackview = dynamic_cast(clicked_trackview); + ret = button_press_handler (item, event, FadeOutHandleItem); + break; + + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, FadeOutHandleItem); + break; + + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, FadeOutHandleItem); + break; + + case GDK_ENTER_NOTIFY: + ret = enter_handler (item, event, FadeOutHandleItem); + break; + + case GDK_LEAVE_NOTIFY: + ret = leave_handler (item, event, FadeOutHandleItem); + break; + + default: + break; + } + + return ret; +} + +struct DescendingRegionLayerSorter { + bool operator()(Region* a, Region* b) { + return a->layer() > b->layer(); + } +}; + +gint +Editor::canvas_crossfade_view_event (GtkCanvasItem* item, GdkEvent* event, CrossfadeView* xfv) +{ + /* we handle only button 3 press/release events */ + + switch (event->type) { + case GDK_BUTTON_PRESS: + clicked_crossfadeview = xfv; + clicked_trackview = &clicked_crossfadeview->get_time_axis_view(); + if (event->button.button == 3) { + return button_press_handler (item, event, CrossfadeViewItem); + } + break; + + case GDK_BUTTON_RELEASE: + if (event->button.button == 3) { + gint ret = button_release_handler (item, event, CrossfadeViewItem); + return ret; + } + break; + + default: + break; + + } + + + /* proxy for the upper most regionview */ + + /* XXX really need to check if we are in the name highlight, + and proxy to that when required. + */ + + TimeAxisView& tv (xfv->get_time_axis_view()); + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast(&tv)) != 0) { + + if (atv->is_audio_track()) { + + AudioPlaylist* pl = atv->get_diskstream()->playlist(); + Playlist::RegionList* rl = pl->regions_at (event_frame (event)); + + if (!rl->empty()) { + DescendingRegionLayerSorter cmp; + rl->sort (cmp); + + AudioRegionView* arv = atv->view->find_view (*(dynamic_cast (rl->front()))); + + /* proxy */ + + delete rl; + + return canvas_region_view_event (arv->get_canvas_group(), event, arv); + } + } + } + + return TRUE; +} + +gint +Editor::canvas_control_point_event (GtkCanvasItem *item, GdkEvent *event) +{ + ItemType type; + ControlPoint *cp; + + if ((cp = static_cast (gtk_object_get_data (GTK_OBJECT(item), "control_point"))) == 0) { + fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg; + /*NOTREACHED*/ + } + + if (dynamic_cast (&cp->line) != 0) { + type = GainControlPointItem; + } else if (dynamic_cast (&cp->line) != 0) { + type = GainAutomationControlPointItem; + } else if (dynamic_cast (&cp->line) != 0) { + type = PanAutomationControlPointItem; + } else if (dynamic_cast (&cp->line) != 0) { + type = RedirectAutomationControlPointItem; + } else { + return FALSE; + } + + return typed_event (item, event, type); +} + +gint +Editor::canvas_line_event (GtkCanvasItem *item, GdkEvent *event) +{ + ItemType type; + AutomationLine *al; + + if ((al = static_cast (gtk_object_get_data (GTK_OBJECT(item), "line"))) == 0) { + fatal << _("programming error: line canvas item has no line object pointer!") << endmsg; + /*NOTREACHED*/ + } + + if (dynamic_cast (al) != 0) { + type = GainLineItem; + } else if (dynamic_cast (al) != 0) { + type = GainAutomationLineItem; + } else if (dynamic_cast (al) != 0) { + type = PanAutomationLineItem; + } else if (dynamic_cast (al) != 0) { + type = RedirectAutomationLineItem; + } else { + return FALSE; + } + + return typed_event (item, event, type); +} + + +gint +Editor::canvas_selection_rect_event (GtkCanvasItem *item, GdkEvent *event) +{ + gint ret = FALSE; + SelectionRect *rect = 0; + + if ((rect = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "rect"))) == 0) { + fatal << _("programming error: no \"rect\" pointer associated with selection item") << endmsg; + /*NOTREACHED*/ + } + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_selection = rect->id; + ret = button_press_handler (item, event, SelectionItem); + break; + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, SelectionItem); + break; + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, SelectionItem); + break; + /* Don't need these at the moment. */ + case GDK_ENTER_NOTIFY: + ret = enter_handler (item, event, SelectionItem); + break; + + case GDK_LEAVE_NOTIFY: + ret = leave_handler (item, event, SelectionItem); + break; + + default: + break; + } + + return ret; +} + +gint +Editor::canvas_selection_start_trim_event (GtkCanvasItem *item, GdkEvent *event) +{ + gint ret = FALSE; + SelectionRect *rect = 0; + + if ((rect = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "rect"))) == 0) { + fatal << _("programming error: no \"rect\" pointer associated with selection item") << endmsg; + /*NOTREACHED*/ + } + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_selection = rect->id; + ret = button_press_handler (item, event, StartSelectionTrimItem); + break; + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, StartSelectionTrimItem); + break; + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, StartSelectionTrimItem); + break; + case GDK_ENTER_NOTIFY: + ret = enter_handler (item, event, StartSelectionTrimItem); + break; + + case GDK_LEAVE_NOTIFY: + ret = leave_handler (item, event, StartSelectionTrimItem); + break; + + default: + break; + } + + return ret; +} + +gint +Editor::canvas_selection_end_trim_event (GtkCanvasItem *item, GdkEvent *event) +{ + gint ret = FALSE; + SelectionRect *rect = 0; + + if ((rect = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "rect"))) == 0) { + fatal << _("programming error: no \"rect\" pointer associated with selection item") << endmsg; + /*NOTREACHED*/ + } + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_selection = rect->id; + ret = button_press_handler (item, event, EndSelectionTrimItem); + break; + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, EndSelectionTrimItem); + break; + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, EndSelectionTrimItem); + break; + case GDK_ENTER_NOTIFY: + ret = enter_handler (item, event, EndSelectionTrimItem); + break; + + case GDK_LEAVE_NOTIFY: + ret = leave_handler (item, event, EndSelectionTrimItem); + break; + + default: + break; + } + + return ret; +} + + +gint +Editor::canvas_region_view_name_highlight_event (GtkCanvasItem *item, GdkEvent *event) +{ + gint ret = FALSE; + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_regionview = reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "regionview")); + clicked_control_point = 0; + clicked_trackview = &clicked_regionview->get_time_axis_view(); + clicked_audio_trackview = dynamic_cast(clicked_trackview); + ret = button_press_handler (item, event, AudioRegionViewNameHighlight); + break; + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, AudioRegionViewNameHighlight); + break; + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, AudioRegionViewNameHighlight); + break; + case GDK_ENTER_NOTIFY: + ret = enter_handler (item, event, AudioRegionViewNameHighlight); + break; + + case GDK_LEAVE_NOTIFY: + ret = leave_handler (item, event, AudioRegionViewNameHighlight); + break; + + default: + break; + } + + return ret; +} + +gint +Editor::canvas_region_view_name_event (GtkCanvasItem *item, GdkEvent *event) +{ + gint ret = FALSE; + + switch (event->type) { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_regionview = reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "regionview")); + clicked_control_point = 0; + clicked_trackview = &clicked_regionview->get_time_axis_view(); + clicked_audio_trackview = dynamic_cast(clicked_trackview); + ret = button_press_handler (item, event, AudioRegionViewName); + break; + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, AudioRegionViewName); + break; + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, AudioRegionViewName); + break; + case GDK_ENTER_NOTIFY: + ret = enter_handler (item, event, AudioRegionViewName); + break; + + case GDK_LEAVE_NOTIFY: + ret = leave_handler (item, event, AudioRegionViewName); + break; + + default: + break; + } + + return ret; +} + +gint +Editor::canvas_marker_event (GtkCanvasItem *item, GdkEvent *event) +{ + return typed_event (item, event, MarkerItem); +} + +gint +Editor::canvas_marker_bar_event (GtkCanvasItem *item, GdkEvent *event) +{ + return typed_event (item, event, MarkerBarItem); +} + +gint +Editor::canvas_range_marker_bar_event (GtkCanvasItem *item, GdkEvent *event) +{ + return typed_event (item, event, RangeMarkerBarItem); +} + +gint +Editor::canvas_transport_marker_bar_event (GtkCanvasItem *item, GdkEvent *event) +{ + return typed_event (item, event, TransportMarkerBarItem); +} + +gint +Editor::canvas_tempo_marker_event (GtkCanvasItem *item, GdkEvent *event) +{ + return typed_event (item, event, TempoMarkerItem); +} + +gint +Editor::canvas_meter_marker_event (GtkCanvasItem *item, GdkEvent *event) +{ + return typed_event (item, event, MeterMarkerItem); +} + +gint +Editor::canvas_tempo_bar_event (GtkCanvasItem *item, GdkEvent *event) +{ + return typed_event (item, event, TempoBarItem); +} + +gint +Editor::canvas_meter_bar_event (GtkCanvasItem *item, GdkEvent *event) +{ + return typed_event (item, event, MeterBarItem); +} + +gint +Editor::canvas_playhead_cursor_event (GtkCanvasItem *item, GdkEvent *event) +{ + return typed_event (item, event, PlayheadCursorItem); +} + +gint +Editor::canvas_edit_cursor_event (GtkCanvasItem *item, GdkEvent *event) +{ + return typed_event (item, event, EditCursorItem); +} + +gint +Editor::canvas_zoom_rect_event (GtkCanvasItem *item, GdkEvent *event) +{ + return typed_event (item, event, NoItem); +} + +gint +Editor::canvas_copy_region_event (GtkCanvasItem *item, GdkEvent *event) +{ + return typed_event (item, event, RegionItem); +} + diff --git a/gtk2_ardour/editor_cursors.cc b/gtk2_ardour/editor_cursors.cc new file mode 100644 index 0000000000..0afbee4fdd --- /dev/null +++ b/gtk2_ardour/editor_cursors.cc @@ -0,0 +1,121 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include + +#include "utils.h" +#include "editor.h" + +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; + +Editor::Cursor::Cursor (Editor& ed, const string& color, GtkSignalFunc callbck) + : editor (ed), callback (callbck), length(1.0) +{ + GtkCanvasGroup *group; + points = gtk_canvas_points_new (2); + + /* "randomly" initialize coords */ + + points->coords[0] = -9383839.0; + points->coords[1] = 0.0; + points->coords[2] = 1.0; + points->coords[3] = 0.0; + + group = GTK_CANVAS_GROUP (editor.cursor_group); + + // cerr << "set cursor points, nc = " << points->num_points << endl; + canvas_item = gtk_canvas_item_new (group, + gtk_canvas_line_get_type(), + "points", points, + "fill_color", color.c_str(), + "width_pixels", 1, + "first_arrowhead", (gboolean) TRUE, + "last_arrowhead", (gboolean) TRUE, + "arrow_shape_a", 11.0, + "arrow_shape_b", 0.0, + "arrow_shape_c", 9.0, + NULL); + + // cerr << "cursor line @ " << canvas_item << endl; + + gtk_object_set_data (GTK_OBJECT(canvas_item), "cursor", this); + gtk_signal_connect (GTK_OBJECT(canvas_item), "event", callback, &editor); + + current_frame = 1; /* force redraw at 0 */ +} + +Editor::Cursor::~Cursor () + +{ + gtk_object_destroy (GTK_OBJECT(canvas_item)); + gtk_canvas_points_unref (points); +} + +void +Editor::Cursor::set_position (jack_nframes_t frame) +{ + double new_pos = editor.frame_to_unit (frame); + + if (editor.session == 0) { + gtk_canvas_item_hide (canvas_item); + } else { + gtk_canvas_item_show (canvas_item); + } + + current_frame = frame; + + if (new_pos == points->coords[0]) { + + /* change in position is not visible, so just raise it */ + + gtk_canvas_item_raise_to_top (canvas_item); + return; + } + + points->coords[0] = new_pos; + points->coords[2] = new_pos; + + // cerr << "set cursor2 al points, nc = " << points->num_points << endl; + gtk_canvas_item_set (canvas_item, "points", points, NULL); + gtk_canvas_item_raise_to_top (canvas_item); +} + +void +Editor::Cursor::set_length (double units) +{ + length = units; + points->coords[3] = points->coords[1] + length; + // cerr << "set cursor3 al points, nc = " << points->num_points << endl; + gtk_canvas_item_set (canvas_item, "points", points, NULL); +} + +void +Editor::Cursor::set_y_axis (double position) +{ + points->coords[1] = position; + points->coords[3] = position + length; + // cerr << "set cursor4 al points, nc = " << points->num_points << endl; + gtk_canvas_item_set (canvas_item, "points", points, NULL); +} diff --git a/gtk2_ardour/editor_edit_groups.cc b/gtk2_ardour/editor_edit_groups.cc new file mode 100644 index 0000000000..8af7d31f5d --- /dev/null +++ b/gtk2_ardour/editor_edit_groups.cc @@ -0,0 +1,210 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include +#include + +#include "editor.h" +#include "keyboard.h" +#include "marker.h" +#include "time_axis_view.h" +#include "prompter.h" + +#include + +#include "i18n.h" + +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; + +void +Editor::edit_group_list_column_click (gint col) + +{ + if (edit_group_list_menu == 0) { + build_edit_group_list_menu (); + } + + edit_group_list_menu->popup (0, 0); +} + +void +Editor::build_edit_group_list_menu () + +{ + using namespace Gtk::Menu_Helpers; + + edit_group_list_menu = new Menu; + edit_group_list_menu->set_name ("ArdourContextMenu"); + MenuList& items = edit_group_list_menu->items(); + + items.push_back (MenuElem (_("Show All"), slot (*this, &Editor::select_all_edit_groups))); + items.push_back (MenuElem (_("Hide All"), slot (*this, &Editor::unselect_all_edit_groups))); +} + +void +Editor::unselect_all_edit_groups () + +{ +} + +void +Editor::select_all_edit_groups () + +{ + CList_Helpers::RowList::iterator i; + + /* XXX potential race with remove_track(), but the select operation + cannot be done with the track_lock held. + */ + + for (i = route_list.rows().begin(); i != route_list.rows().end(); ++i) { + i->select (); + } +} + +void +Editor::new_edit_group () + +{ + if (session == 0) { + return; + } + + ArdourPrompter prompter; + string result; + + prompter.set_prompt (_("Name for new edit group")); + prompter.done.connect (Gtk::Main::quit.slot()); + + prompter.show_all (); + + Gtk::Main::run (); + + if (prompter.status != Gtkmmext::Prompter::entered) { + return; + } + + prompter.get_result (result); + + if (result.length()) { + session->add_edit_group (result); + } +} + +void +Editor::edit_group_list_button_clicked () +{ + new_edit_group (); +} + +gint +Editor::edit_group_list_button_press_event (GdkEventButton* ev) +{ + gint row, col; + + if (edit_group_list.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) { + return FALSE; + } + + if (col == 1) { + + if (Keyboard::is_edit_event (ev)) { + // RouteGroup* group = (RouteGroup *) edit_group_list.row(row).get_data (); + // edit_route_group (group); + + return stop_signal (edit_group_list, "button_press_event"); + + } else { + /* allow regular select to occur */ + return FALSE; + } + + } else if (col == 0) { + + RouteGroup* group = reinterpret_cast(edit_group_list.row(row).get_data ()); + + if (group) { + group->set_active (!group->is_active(), this); + } + } + + return stop_signal (edit_group_list, "button_press_event"); +} + +void +Editor::edit_group_selected (gint row, gint col, GdkEvent* ev) +{ + RouteGroup* group = (RouteGroup *) edit_group_list.row(row).get_data (); + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + if ((*i)->edit_group() == group) { + select_strip_in_display (*(*i)); + } + } +} + +void +Editor::edit_group_unselected (gint row, gint col, GdkEvent* ev) +{ + RouteGroup* group = (RouteGroup *) edit_group_list.row(row).get_data (); + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + if ((*i)->edit_group() == group) { + unselect_strip_in_display (*(*i)); + } + } +} + +void +Editor::add_edit_group (RouteGroup* group) +{ + list names; + + names.push_back ("*"); + names.push_back (group->name()); + + edit_group_list.rows().push_back (names); + edit_group_list.rows().back().set_data (group); + edit_group_list.rows().back().select(); + + group->FlagsChanged.connect (bind (slot (*this, &Editor::group_flags_changed), group)); +} + +void +Editor::group_flags_changed (void* src, RouteGroup* group) +{ + if (src != this) { + // select row + } + + CList_Helpers::RowIterator ri = edit_group_list.rows().find_data (group); + + if (group->is_active()) { + edit_group_list.cell (ri->get_row_num(),0).set_pixmap (check_pixmap, check_mask); + } else { + edit_group_list.cell (ri->get_row_num(),0).set_pixmap (empty_pixmap, empty_mask); + } +} + diff --git a/gtk2_ardour/editor_enums.h b/gtk2_ardour/editor_enums.h new file mode 100644 index 0000000000..419f0e2809 --- /dev/null +++ b/gtk2_ardour/editor_enums.h @@ -0,0 +1,10 @@ +#ifndef __ardour_gtk_editor_enums_h__ +#define __ardour_gtk_editor_enums_h__ + +enum EditorDisplayControl { + ShowMeasures, + ShowWaveforms, + FollowPlayhead +}; + +#endif /* __ardour_gtk_editor_enums_h__ */ diff --git a/gtk2_ardour/editor_export_audio.cc b/gtk2_ardour/editor_export_audio.cc new file mode 100644 index 0000000000..b4ee6eecdf --- /dev/null +++ b/gtk2_ardour/editor_export_audio.cc @@ -0,0 +1,437 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include "export_dialog.h" +#include "editor.h" +#include "public_editor.h" +#include "selection.h" +#include "time_axis_view.h" +#include "audio_time_axis.h" +#include "regionview.h" +#include "ardour_message.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; +using namespace Gtk; + +void +Editor::export_session() +{ + if (session) { + export_range (0, session->current_end_frame()); + } +} + +void +Editor::export_selection () +{ + if (session) { + if (selection->time.empty()) { + ArdourMessage message (this, X_("norange"), _("There is no range to export.\n\nSelect a range using the range mouse mode")); + return; + } + + export_range (selection->time.front().start, + selection->time.front().end); + } +} + +void +Editor::export_range (jack_nframes_t start, jack_nframes_t end) +{ + if (session) { + if (export_dialog == 0) { + export_dialog = new ExportDialog (*this); + } + + export_dialog->connect_to_session (session); + export_dialog->set_range (start, end); + export_dialog->start_export(); + } +} + +void +Editor::export_region () +{ + if (clicked_regionview == 0) { + return; + } + + ExportDialog* dialog = new ExportDialog (*this, &clicked_regionview->region); + + dialog->connect_to_session (session); + dialog->set_range (0, clicked_regionview->region.length()); + dialog->start_export(); +} + +void +Editor::write_a_region () +{ + if (clicked_regionview == 0) { + return; + } + + FileSelection file_selector; + + file_selector.get_selection_entry()->activate.connect (bind (slot (*this, &Editor::finish_sub_event_loop), 1)); + file_selector.get_cancel_button()->clicked.connect (bind (slot (*this, &Editor::finish_sub_event_loop), -1)); + file_selector.get_ok_button()->clicked.connect (bind (slot (*this, &Editor::finish_sub_event_loop), 1)); + file_selector.delete_event.connect (bind (slot (*this, &Editor::finish_sub_event_loop_on_delete), -1)); + + file_selector.show_all(); + + run_sub_event_loop (); + + if (sub_event_loop_status == 1) { + string path = file_selector.get_filename(); + printf ("got region: %s\n", path.c_str()); + if (path.length()) { + write_region (path, clicked_regionview->region); + } + } +} + +int +Editor::write_region_selection (AudioRegionSelection& regions) +{ + for (AudioRegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) { + if (write_region ("", (*i)->region) == false) { + return -1; + } + } + return 0; +} + +void +Editor::bounce_region_selection () +{ + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + + AudioRegion& region ((*i)->region); + AudioTimeAxisView* atv = dynamic_cast(&(*i)->get_time_axis_view()); + AudioTrack* track = dynamic_cast(&(atv->route())); + + InterThreadInfo itt; + + itt.done = false; + itt.cancel = false; + itt.progress = 0.0f; + + track->bounce_range (region.position(), region.position() + region.length(), itt); + } +} + +bool +Editor::write_region (string path, AudioRegion& region) +{ + FileSource* fs; + const jack_nframes_t chunk_size = 4096; + jack_nframes_t to_read; + Sample buf[chunk_size]; + gain_t gain_buffer[chunk_size]; + jack_nframes_t pos; + char s[PATH_MAX+1]; + uint32_t cnt; + vector sources; + uint32_t nchans; + + nchans = region.n_channels(); + + /* don't do duplicate of the entire source if that's what is going on here */ + + if (region.start() == 0 && region.length() == region.source().length()) { + /* XXX should link(2) to create a new inode with "path" */ + return true; + } + + if (path.length() == 0) { + + for (uint32_t n=0; n < nchans; ++n) { + + for (cnt = 0; cnt < 999999; ++cnt) { + if (nchans == 1) { + snprintf (s, sizeof(s), "%s/%s_%" PRIu32 ".wav", session->sound_dir().c_str(), + legalize_for_path(region.name()).c_str(), cnt); + } + else { + snprintf (s, sizeof(s), "%s/%s_%" PRIu32 "-%" PRId32 ".wav", session->sound_dir().c_str(), + legalize_for_path(region.name()).c_str(), cnt, n); + } + + path = s; + + if (::access (path.c_str(), F_OK) != 0) { + break; + } + } + + if (cnt == 999999) { + error << "" << endmsg; + goto error_out; + } + + + + try { + fs = new FileSource (path, session->frame_rate()); + } + + catch (failed_constructor& err) { + goto error_out; + } + + sources.push_back (fs); + } + } + else { + /* TODO: make filesources based on passed path */ + + } + + to_read = region.length(); + pos = region.position(); + + while (to_read) { + jack_nframes_t this_time; + + this_time = min (to_read, chunk_size); + + for (vector::iterator src=sources.begin(); src != sources.end(); ++src) { + + fs = (*src); + + if (region.read_at (buf, buf, gain_buffer, pos, this_time) != this_time) { + break; + } + + if (fs->write (buf, this_time) != this_time) { + error << "" << endmsg; + goto error_out; + } + } + + to_read -= this_time; + pos += this_time; + } + + time_t tnow; + struct tm* now; + time (&tnow); + now = localtime (&tnow); + + for (vector::iterator src = sources.begin(); src != sources.end(); ++src) { + (*src)->update_header (0, *now, tnow); + } + + return true; + +error_out: + + for (vector::iterator i = sources.begin(); i != sources.end(); ++i) { + (*i)->mark_for_remove (); + delete (*i); + } + + return 0; +} + +int +Editor::write_audio_selection (TimeSelection& ts) +{ + int ret = 0; + + if (selection->tracks.empty()) { + return 0; + } + + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast(*i)) == 0) { + continue; + } + + if (atv->is_audio_track()) { + + Playlist* playlist = atv->get_diskstream()->playlist(); + + if (playlist && write_audio_range (*playlist, atv->get_diskstream()->n_channels(), ts) == 0) { + ret = -1; + break; + } + } + } + + return ret; +} + +bool +Editor::write_audio_range (Playlist& playlist, uint32_t channels, list& range) +{ + FileSource* fs; + const jack_nframes_t chunk_size = 4096; + jack_nframes_t nframes; + Sample buf[chunk_size]; + gain_t gain_buffer[chunk_size]; + jack_nframes_t pos; + char s[PATH_MAX+1]; + uint32_t cnt; + string path; + vector sources; + + for (uint32_t n=0; n < channels; ++n) { + + for (cnt = 0; cnt < 999999; ++cnt) { + if (channels == 1) { + snprintf (s, sizeof(s), "%s/%s_%" PRIu32 ".wav", session->sound_dir().c_str(), + legalize_for_path(playlist.name()).c_str(), cnt); + } + else { + snprintf (s, sizeof(s), "%s/%s_%" PRIu32 "-%" PRId32 ".wav", session->sound_dir().c_str(), + legalize_for_path(playlist.name()).c_str(), cnt, n); + } + + if (::access (s, F_OK) != 0) { + break; + } + } + + if (cnt == 999999) { + error << "" << endmsg; + goto error_out; + } + + path = s; + + try { + fs = new FileSource (path, session->frame_rate()); + } + + catch (failed_constructor& err) { + goto error_out; + } + + sources.push_back (fs); + + } + + + for (list::iterator i = range.begin(); i != range.end();) { + + nframes = (*i).length(); + pos = (*i).start; + + while (nframes) { + jack_nframes_t this_time; + + this_time = min (nframes, chunk_size); + + for (uint32_t n=0; n < channels; ++n) { + + fs = sources[n]; + + if (playlist.read (buf, buf, gain_buffer, pos, this_time, n) != this_time) { + break; + } + + if (fs->write (buf, this_time) != this_time) { + goto error_out; + } + } + + nframes -= this_time; + pos += this_time; + } + + list::iterator tmp = i; + ++tmp; + + if (tmp != range.end()) { + + /* fill gaps with silence */ + + nframes = (*tmp).start - (*i).end; + + while (nframes) { + + jack_nframes_t this_time = min (nframes, chunk_size); + memset (buf, 0, sizeof (Sample) * this_time); + + for (uint32_t n=0; n < channels; ++n) { + + fs = sources[n]; + if (fs->write (buf, this_time) != this_time) { + goto error_out; + } + } + + nframes -= this_time; + } + } + + i = tmp; + } + + time_t tnow; + struct tm* now; + time (&tnow); + now = localtime (&tnow); + + for (uint32_t n=0; n < channels; ++n) { + sources[n]->update_header (0, *now, tnow); + // do we need to ref it again? + } + + return true; + +error_out: + /* unref created files */ + + for (vector::iterator i = sources.begin(); i != sources.end(); ++i) { + (*i)->mark_for_remove (); + delete *i; + } + + return false; +} + +void +Editor::write_selection () +{ + if (!selection->time.empty()) { + write_audio_selection (selection->time); + } else if (!selection->audio_regions.empty()) { + write_region_selection (selection->audio_regions); + } +} diff --git a/gtk2_ardour/editor_hscroller.cc b/gtk2_ardour/editor_hscroller.cc new file mode 100644 index 0000000000..d22c1e69ed --- /dev/null +++ b/gtk2_ardour/editor_hscroller.cc @@ -0,0 +1,270 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include "editor.h" + +#include + +using namespace std; +using namespace ARDOUR; + +void +Editor::hscroll_slider_allocate (GtkAllocation *alloc) +{ + //edit_hscroll_slider_width = alloc->width; + //edit_hscroll_slider_height = alloc->height ; + + if (session) { + track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit); + } + +} + +gint +Editor::hscroll_slider_expose (GdkEventExpose *ev) +{ + GdkRectangle draw_rect; + GdkRectangle bar_rect; + gint bar_max = edit_hscroll_slider_width - 2; + + bar_rect.y = 1; + bar_rect.height = edit_hscroll_slider_height - 2; + + if (session) { + bar_rect.width = (gint) floor (bar_max * ((canvas_width * frames_per_unit) / session->current_end_frame())); + + if (bar_rect.width > bar_max) { + bar_rect.x = 1; + bar_rect.width = bar_max; + } else { + bar_rect.x = 1 + (gint) floor (bar_max * ((double) leftmost_frame / session->current_end_frame())); + } + + } else { + bar_rect.x = 1; + bar_rect.width = bar_max; + } + + /* make sure we can see the bar at all times, and have enough to do zoom-trim on */ + + bar_rect.width = max ((guint16) (edit_hscroll_edge_width+5), bar_rect.width); + + gdk_rectangle_intersect (&ev->area, &bar_rect, &draw_rect); + + gtk_paint_box (edit_hscroll_slider.get_style()->gtkobj(), + edit_hscroll_slider.get_window(), + GTK_STATE_ACTIVE, + GTK_SHADOW_IN, + &ev->area, + GTK_WIDGET(edit_hscroll_slider.gtkobj()), + "trough", + 0, 0, -1, -1); + + gtk_paint_box (edit_hscroll_slider.get_style()->gtkobj(), + edit_hscroll_slider.get_window(), + GTK_STATE_NORMAL, + GTK_SHADOW_OUT, + &draw_rect, + GTK_WIDGET(edit_hscroll_slider.gtkobj()), + "hscale", + bar_rect.x, bar_rect.y, bar_rect.width, bar_rect.height); + + + return TRUE; +} + +gint +Editor::hscroll_slider_button_press (GdkEventButton *ev) +{ + if (!session) { + return TRUE; + } + + edit_hscroll_dragging = true; + //cerr << "PRESS" << endl; + + return TRUE; + + gint start; + gint width; + gint end; + gint x; + + start = (gint) floor (edit_hscroll_slider_width * ((double) leftmost_frame / session->current_end_frame())); + width = (gint) floor (edit_hscroll_slider_width * ((canvas_width * frames_per_unit) / session->current_end_frame())); + + end = start + width - 1; + x = (gint) max (0.0, ev->x); + + if (x >= start && x <= end) { + + edit_hscroll_drag_last = x; + edit_hscroll_dragging = true; + Gtk::Main::grab_add (edit_hscroll_slider); + } + + return TRUE; +} + +gint +Editor::hscroll_slider_button_release (GdkEventButton *ev) +{ + if (!session) { + return TRUE; + } + + gint start; + gint width; + gint end; + gint x; + gint bar_max = edit_hscroll_slider_width - 2; + jack_nframes_t new_leftmost = 0; + + //cerr << "RELESAE" << endl; + + if (edit_hscroll_dragging) { + // lets do a tempo redisplay now only, because it is dog slow + tempo_map_changed (Change (0)); + edit_hscroll_dragging = false; + } + + return TRUE; + + + start = (gint) floor (bar_max * ((double) leftmost_frame / session->current_end_frame())); + width = (gint) floor (bar_max * ((canvas_width * frames_per_unit) / session->current_end_frame())); + + end = start + width - 1; + x = (gint) max (0.0, ev->x); + + if (!edit_hscroll_dragging) { + + new_leftmost = (jack_nframes_t) floor (((double) x/bar_max) * session->current_end_frame()); + reposition_x_origin (new_leftmost); + } + + if (edit_hscroll_dragging) { + // lets do a tempo redisplay now only, because it is dog slow + tempo_map_changed (Change (0)); + edit_hscroll_dragging = false; + Gtk::Main::grab_remove (edit_hscroll_slider); + } + + return TRUE; +} + +gint +Editor::hscroll_slider_motion (GdkEventMotion *ev) +{ + gint x, y; + GdkModifierType state; + gint bar_max = edit_hscroll_slider_width - 2; + + if (!session || !edit_hscroll_dragging) { + return TRUE; + } + + edit_hscroll_slider.get_window().get_pointer (x, y, state); + + jack_nframes_t new_frame; + jack_nframes_t frames; + double distance; + double fract; + + distance = x - edit_hscroll_drag_last; + fract = fabs (distance) / bar_max; + frames = (jack_nframes_t) floor (session->current_end_frame() * fract); + + if (distance < 0) { + if (leftmost_frame < frames) { + new_frame = 0; + } else { + new_frame = leftmost_frame - frames; + } + } else { + if (leftmost_frame > max_frames - frames) { + new_frame = max_frames; + } else { + new_frame = leftmost_frame + frames; + } + } + + if (new_frame != leftmost_frame) { + reposition_x_origin (new_frame); + } + + edit_hscroll_drag_last = x; + + return TRUE; +} + +void +Editor::update_hscroller () +{ + //edit_hscroll_slider.queue_draw (); +// if (session) { +// track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit); +// track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit); +// } +} + +gint +Editor::hscroll_left_arrow_button_press (GdkEventButton *ev) +{ + if (!session) { + return FALSE; + } + + start_canvas_autoscroll (-1); + return TRUE; +} + +gint +Editor::hscroll_right_arrow_button_press (GdkEventButton *ev) +{ + if (!session) { + return FALSE; + } + + start_canvas_autoscroll (1); + return TRUE; +} + +gint +Editor::hscroll_left_arrow_button_release (GdkEventButton *ev) +{ + if (!session) { + return FALSE; + } + + stop_canvas_autoscroll (); + return TRUE; +} + +gint +Editor::hscroll_right_arrow_button_release (GdkEventButton *ev) +{ + if (!session) { + return FALSE; + } + + stop_canvas_autoscroll (); + return TRUE; +} diff --git a/gtk2_ardour/editor_imageframe.cc b/gtk2_ardour/editor_imageframe.cc new file mode 100644 index 0000000000..57dbd0613e --- /dev/null +++ b/gtk2_ardour/editor_imageframe.cc @@ -0,0 +1,1179 @@ +#include "imageframe_view.h" +#include "imageframe_time_axis.h" +#include "imageframe_time_axis_view.h" +#include "imageframe_time_axis_group.h" +#include "marker_time_axis_view.h" +#include "marker_time_axis.h" +#include "marker_view.h" +#include "editor.h" +#include "i18n.h" +#include +#include + +#include +#include +#include +#include +#include + +#include "imageframe_socket_handler.h" +#include "ardour_image_compositor_socket.h" +#include "public_editor.h" + +/* */ + +void +Editor::add_imageframe_time_axis(std::string track_name, void* src) +{ + // check for duplicate name + if(get_named_time_axis(track_name)) + { + warning << "Repeated time axis name" << std::endl ; + } + else + { + Gtkmmext::UI::instance()->call_slot(bind(slot(*this, &Editor::handle_new_imageframe_time_axis_view),track_name, src)) ; + } +} + +void +Editor::connect_to_image_compositor() +{ + if(image_socket_listener == 0) + { + image_socket_listener = ImageFrameSocketHandler::create_instance(*this) ; + } + + if(image_socket_listener->is_connected() == true) + { + return ; + } + + // XXX should really put this somewhere safe + std::string host_ip = "127.0.0.1" ; + + bool retcode = image_socket_listener->connect(host_ip,ardourvis::DEFAULT_PORT) ; + + if(retcode == false) + { + // XXX need to get some return status here + warning << "Image Compositor Connection attempt failed" << std::endl ; + return ; + } + + // add the socket to the gui loop, and keep the retuned tag value of the input + gint tag = gdk_input_add(image_socket_listener->get_socket_descriptor(), GDK_INPUT_READ,ImageFrameSocketHandler::image_socket_callback,image_socket_listener) ; + image_socket_listener->set_gdk_input_tag(tag) ; +} + +void +Editor::scroll_timeaxis_to_imageframe_item(const TimeAxisViewItem* item) +{ + jack_nframes_t offset = static_cast(frames_per_unit * (edit_hscroll_slider_width/2)) ; + + jack_nframes_t x_pos = 0 ; + if(item->get_position() < offset) + { + x_pos = 0 ; + } + else + { + x_pos = item->get_position() - offset + (item->get_duration() / 2) ; + } + + reposition_x_origin(x_pos) ; +} + +void +Editor::add_imageframe_marker_time_axis(std::string track_name, TimeAxisView* marked_track, void* src) +{ + // Can we only bind 2 data Items? + // @todo we really want to bind the src attribute too, for the moment tracks can only be added remotely, + // so this is not too much of an issue, however will need to be looked at again + Gtkmmext::UI::instance()->call_slot(SigC::bind(slot(*this, &Editor::handle_new_imageframe_marker_time_axis_view),track_name, marked_track)) ; +} + +void +Editor::popup_imageframe_edit_menu(int button, int32_t time, GtkCanvasItem* ifv, bool with_item) +{ + ImageFrameTimeAxis* ifta = dynamic_cast(clicked_trackview) ; + + if(ifta) + { + ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_selected_imageframe_group() ; + + if(iftag) + { + ImageFrameView* selected_ifv = ifta->get_view()->get_selected_imageframe_view() ; + ifta->popup_imageframe_edit_menu(button, time, selected_ifv, with_item) ; + } + } +} + +void +Editor::popup_marker_time_axis_edit_menu(int button, int32_t time, GtkCanvasItem* ifv, bool with_item) +{ + MarkerTimeAxis* mta = dynamic_cast(clicked_trackview) ; + + if(mta) + { + MarkerView* selected_mv = mta->get_view()->get_selected_time_axis_item() ; + if(selected_mv) + { + mta->popup_marker_time_axis_edit_menu(button,time, selected_mv, with_item) ; + } + } +} + +TimeAxisView* +Editor::get_named_time_axis(std::string name) +{ + TimeAxisView* tav = 0 ; + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) + { + if (((TimeAxisView*)*i)->name() == name) + { + tav = ((TimeAxisView*)*i) ; + break ; + } + } + return(tav) ; +} + +/* */ + + + + + + +/* */ + +/** + * --------------------------------------------------------------------------------------------------- + * Static event handlers + * These handlers deal with events from the GtkCanvas, a c-based component + */ + + +gint +Editor::_canvas_imageframe_start_handle_event(GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + ImageFrameView* ifv = (ImageFrameView*) data ; + Editor* editor = dynamic_cast (&ifv->get_time_axis_view().editor); + return editor->canvas_imageframe_start_handle_event(item,event,ifv); +} + +gint +Editor::_canvas_imageframe_end_handle_event(GtkCanvasItem *item, GdkEvent *event, gpointer data) +{ + ImageFrameView* ifv = (ImageFrameView*) data ; + Editor* editor = dynamic_cast (&ifv->get_time_axis_view().editor); + return editor->canvas_imageframe_end_handle_event(item,event,ifv); +} + + +gint +Editor::_canvas_imageframe_item_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) +{ + ImageFrameView *ifv = (ImageFrameView *) data ; + Editor* editor = dynamic_cast (&ifv->get_time_axis_view().editor); + return editor->canvas_imageframe_item_view_event (item, event, ifv) ; +} + +gint +Editor::_canvas_imageframe_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) +{ + ImageFrameTimeAxis *ifta = (ImageFrameTimeAxis*) data ; + Editor* editor = dynamic_cast (&ifta->editor); + return editor->canvas_imageframe_view_event (item, event, ifta); +} + +gint +Editor::_canvas_marker_time_axis_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) +{ + MarkerTimeAxis* mta = (MarkerTimeAxis*)data ; + Editor* editor = dynamic_cast (&mta->editor); + return editor->canvas_marker_time_axis_view_event(item,event,mta); +} + +gint +Editor::_canvas_markerview_item_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) +{ + MarkerView* mv = (MarkerView*) data ; + Editor* editor = dynamic_cast (&mv->get_time_axis_view().editor); + return editor->canvas_markerview_item_view_event(item,event,mv); +} + +gint +Editor::_canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) +{ + MarkerView* mv = (MarkerView*)data ; + Editor* editor = dynamic_cast (&mv->get_time_axis_view().editor); + return editor->canvas_markerview_start_handle_event(item,event,mv); +} + +gint +Editor::_canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) +{ + MarkerView* mv = (MarkerView*)data ; + Editor* editor = dynamic_cast (&mv->get_time_axis_view().editor); + return editor->canvas_markerview_end_handle_event(item,event,mv); +} + +/** + * --------------------------------------------------------------------------------------------------- + * End of Static event handlers + */ + +gint +Editor::canvas_imageframe_item_view_event(GtkCanvasItem *item, GdkEvent *event, ImageFrameView *ifv) +{ + gint ret = FALSE ; + ImageFrameTimeAxisGroup* iftag = 0 ; + + switch (event->type) + { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_trackview = &ifv->get_time_axis_view(); + iftag = ifv->get_time_axis_group() ; + dynamic_cast(clicked_trackview)->get_view()->set_selected_imageframe_view(iftag, ifv); + ret = button_press_handler (item, event, ImageFrameItem) ; + break ; + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, ImageFrameItem) ; + break ; + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, ImageFrameItem) ; + break ; + default: + break ; + } + return(ret) ; +} + +gint +Editor::canvas_imageframe_start_handle_event(GtkCanvasItem *item, GdkEvent *event, ImageFrameView *ifv) +{ + gint ret = FALSE ; + ImageFrameTimeAxisGroup* iftag = 0 ; + + switch (event->type) + { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_trackview = &ifv->get_time_axis_view() ; + iftag = ifv->get_time_axis_group() ; + dynamic_cast(clicked_trackview)->get_view()->set_selected_imageframe_view(iftag, ifv); + + ret = button_press_handler (item, event, ImageFrameHandleStartItem) ; + break ; + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, ImageFrameHandleStartItem) ; + break; + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, ImageFrameHandleStartItem) ; + break ; + case GDK_ENTER_NOTIFY: + ret = enter_handler (item, event, ImageFrameHandleStartItem) ; + break ; + case GDK_LEAVE_NOTIFY: + ret = leave_handler (item, event, ImageFrameHandleStartItem) ; + break ; + default: + break ; + } + return(ret) ; +} + +gint +Editor::canvas_imageframe_end_handle_event(GtkCanvasItem *item, GdkEvent *event, ImageFrameView *ifv) +{ + gint ret = FALSE ; + ImageFrameTimeAxisGroup* iftag = 0 ; + + switch (event->type) + { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_trackview = &ifv->get_time_axis_view() ; + iftag = ifv->get_time_axis_group() ; + dynamic_cast(clicked_trackview)->get_view()->set_selected_imageframe_view(iftag, ifv); + + ret = button_press_handler (item, event, ImageFrameHandleEndItem) ; + break ; + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, ImageFrameHandleEndItem) ; + break ; + case GDK_MOTION_NOTIFY: + ret = motion_handler (item, event, ImageFrameHandleEndItem) ; + break ; + case GDK_ENTER_NOTIFY: + ret = enter_handler (item, event, ImageFrameHandleEndItem) ; + break ; + case GDK_LEAVE_NOTIFY: + ret = leave_handler (item, event, ImageFrameHandleEndItem); + break ; + default: + break ; + } + return(ret) ; +} + +gint +Editor::canvas_imageframe_view_event(GtkCanvasItem* item, GdkEvent* event, ImageFrameTimeAxis* ifta) +{ + gint ret = FALSE ; + switch (event->type) + { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_trackview = ifta ; + ret = button_press_handler (item, event, ImageFrameTimeAxisItem) ; + break ; + case GDK_BUTTON_RELEASE: + ret = button_release_handler (item, event, ImageFrameTimeAxisItem) ; + break ; + case GDK_MOTION_NOTIFY: + break ; + default: + break ; + } + return(ret) ; +} + +gint +Editor::canvas_marker_time_axis_view_event(GtkCanvasItem *item, GdkEvent* event, MarkerTimeAxis* mta) +{ + gint ret = FALSE ; + switch (event->type) + { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_trackview = mta ; + ret = button_press_handler(item, event, MarkerTimeAxisItem) ; + break ; + case GDK_BUTTON_RELEASE: + ret = button_release_handler(item, event, MarkerTimeAxisItem) ; + break ; + case GDK_MOTION_NOTIFY: + default: + break ; + } + return(ret) ; +} + + +gint +Editor::canvas_markerview_item_view_event(GtkCanvasItem *item, GdkEvent* event, MarkerView* mta) +{ + gint ret = FALSE ; + switch (event->type) + { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_trackview = &mta->get_time_axis_view() ; + dynamic_cast(clicked_trackview)->get_view()->set_selected_time_axis_item(mta); + ret = button_press_handler(item, event, MarkerViewItem) ; + break ; + case GDK_BUTTON_RELEASE: + ret = button_release_handler(item, event, MarkerViewItem) ; + break ; + case GDK_MOTION_NOTIFY: + ret = motion_handler(item, event, MarkerViewItem) ; + break ; + default: + break ; + } + return(ret) ; +} + +gint +Editor::canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, MarkerView* mta) +{ + gint ret = FALSE ; + switch (event->type) + { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_trackview = &mta->get_time_axis_view() ; + dynamic_cast(clicked_trackview)->get_view()->set_selected_time_axis_item(mta) ; + ret = button_press_handler(item, event, MarkerViewHandleStartItem) ; + break ; + case GDK_BUTTON_RELEASE: + ret = button_release_handler(item, event, MarkerViewHandleStartItem) ; + break ; + case GDK_MOTION_NOTIFY: + ret = motion_handler(item, event, MarkerViewHandleStartItem) ; + break ; + case GDK_ENTER_NOTIFY: + ret = enter_handler(item, event, MarkerViewHandleStartItem) ; + break ; + case GDK_LEAVE_NOTIFY: + ret = leave_handler(item, event, MarkerViewHandleStartItem) ; + break ; + default: + break ; + } + return(ret) ; +} + +gint +Editor::canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, MarkerView* mta) +{ + gint ret = FALSE ; + switch (event->type) + { + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + clicked_trackview = &mta->get_time_axis_view() ; + dynamic_cast(clicked_trackview)->get_view()->set_selected_time_axis_item(mta) ; + ret = button_press_handler(item, event, MarkerViewHandleEndItem) ; + break ; + case GDK_BUTTON_RELEASE: + ret = button_release_handler(item, event, MarkerViewHandleEndItem) ; + break ; + case GDK_MOTION_NOTIFY: + ret = motion_handler(item, event, MarkerViewHandleEndItem) ; + break ; + case GDK_ENTER_NOTIFY: + ret = enter_handler(item, event, MarkerViewHandleEndItem) ; + break ; + case GDK_LEAVE_NOTIFY: + ret = leave_handler(item, event, MarkerViewHandleEndItem) ; + break ; + default: + break ; + } + return(ret) ; +} + + +/* */ + + +/* + --------------------------------------------------------------------------------------------------- + --------------------------------------------------------------------------------------------------- + --------------------------------------------------------------------------------------------------- +*/ + + + +/* */ + +void +Editor::start_imageframe_grab(GtkCanvasItem* item, GdkEvent* event) +{ + ImageFrameView* ifv = ((ImageFrameTimeAxis*)clicked_trackview)->get_view()->get_selected_imageframe_view() ; + drag_info.copy = false ; + drag_info.item = item ; + drag_info.data = ifv ; + drag_info.motion_callback = &Editor::imageframe_drag_motion_callback; + drag_info.finished_callback = &Editor::timeaxis_item_drag_finished_callback; + drag_info.last_frame_position = ifv->get_position() ; + + drag_info.last_trackview = &ifv->get_time_axis_view() ; + + /* this is subtle. raising the regionview itself won't help, + because raise_to_top() just puts the item on the top of + its parent's stack. so, we need to put the trackview canvas_display group + on the top, since its parent is the whole canvas. + + however, this hides the measure bars within that particular trackview, + so move them to the top afterwards. + */ + + gtk_canvas_item_raise_to_top(drag_info.item) ; + gtk_canvas_item_raise_to_top(drag_info.last_trackview->canvas_display) ; + //gtk_canvas_item_raise_to_top(time_line_group) ; + gtk_canvas_item_raise_to_top (cursor_group); + + start_grab(event) ; + + drag_info.pointer_frame_offset = pixel_to_frame(drag_info.grab_x) - drag_info.last_frame_position; +} + + +void +Editor::start_markerview_grab(GtkCanvasItem* item, GdkEvent* event) +{ + MarkerView* mv = ((MarkerTimeAxis*)clicked_trackview)->get_view()->get_selected_time_axis_item() ; + drag_info.copy = false ; + drag_info.item = item ; + drag_info.data = mv ; + drag_info.motion_callback = &Editor::markerview_drag_motion_callback; + drag_info.finished_callback = &Editor::timeaxis_item_drag_finished_callback; + drag_info.last_frame_position = mv->get_position() ; + + drag_info.last_trackview = &mv->get_time_axis_view() ; + + /* this is subtle. raising the regionview itself won't help, + because raise_to_top() just puts the item on the top of + its parent's stack. so, we need to put the trackview canvas_display group + on the top, since its parent is the whole canvas. + + however, this hides the measure bars within that particular trackview, + so move them to the top afterwards. + */ + + gtk_canvas_item_raise_to_top(drag_info.item) ; + gtk_canvas_item_raise_to_top(drag_info.last_trackview->canvas_display) ; + //gtk_canvas_item_raise_to_top(time_line_group) ; + gtk_canvas_item_raise_to_top (cursor_group); + + start_grab(event) ; + + drag_info.pointer_frame_offset = pixel_to_frame(drag_info.grab_x) - drag_info.last_frame_position ; +} + + +void +Editor::markerview_drag_motion_callback(GtkCanvasItem*, GdkEvent* event) +{ + double cx, cy ; + + MarkerView* mv = reinterpret_cast(drag_info.data) ; + jack_nframes_t pending_region_position ; + jack_nframes_t pointer_frame ; + + pointer_frame = event_frame(event, &cx, &cy) ; + + snap_to(pointer_frame) ; + + if (pointer_frame > (jack_nframes_t) drag_info.pointer_frame_offset) + { + pending_region_position = pointer_frame - drag_info.pointer_frame_offset ; + snap_to(pending_region_position) ; + + // we dont allow marker items to extend beyond, or in front of the marked items so + // cap the value to the marked items position and duration + if((pending_region_position + mv->get_duration()) >= ((mv->get_marked_item()->get_position()) + (mv->get_marked_item()->get_duration()))) + { + pending_region_position = (mv->get_marked_item()->get_position() + mv->get_marked_item()->get_duration()) - (mv->get_duration()) ; + } + else if(pending_region_position <= mv->get_marked_item()->get_position()) + { + pending_region_position = mv->get_marked_item()->get_position() ; + } + } + else + { + pending_region_position = mv->get_marked_item()->get_position() ; + } + + drag_info.last_frame_position = pending_region_position ; + + // we treat this as a special case, usually we want to send the identitiy of the caller + // but in this case, that would trigger our socket handler to handle the event, sending + // notification to the image compositor. This would be fine, except that we have not + // finished the drag, we therefore do not want to sent notification until we have + // completed the drag, only then do we want the image compositor notofied. + // We therefore set the caller identity to the special case of 0 + mv->set_position(pending_region_position, 0) ; + + show_verbose_time_cursor(pending_region_position) ; +} + +void +Editor::imageframe_drag_motion_callback(GtkCanvasItem*, GdkEvent* event) +{ + double cx, cy ; + + ImageFrameView* ifv = reinterpret_cast(drag_info.data) ; + + jack_nframes_t pending_region_position; + jack_nframes_t pointer_frame; + + pointer_frame = event_frame(event, &cx, &cy) ; + + snap_to(pointer_frame) ; + + if (pointer_frame > (jack_nframes_t) drag_info.pointer_frame_offset) + { + pending_region_position = pointer_frame - drag_info.pointer_frame_offset ; + snap_to(pending_region_position) ; + } + else + { + pending_region_position = 0 ; + } + + drag_info.grab_x = cx; + //drag_info.last_frame_position = pending_region_position ; + drag_info.current_pointer_frame = pending_region_position ; + + // we treat this as a special case, usually we want to send the identitiy of the caller + // but in this case, that would trigger our socket handler to handle the event, sending + // notification to the image compositor. This would be fine, except that we have not + // finished the drag, we therefore do not want to sent notification until we have + // completed the drag, only then do we want the image compositor notofied. + // We therefore set the caller identity to the special case of 0 + ifv->set_position(pending_region_position, 0) ; + + show_verbose_time_cursor(pending_region_position) ; +} + +void +Editor::timeaxis_item_drag_finished_callback(GtkCanvasItem*, GdkEvent* event) +{ + jack_nframes_t where ; + TimeAxisViewItem* tavi = reinterpret_cast(drag_info.data) ; + + bool item_x_movement = (drag_info.last_frame_position != tavi->get_position()) ; + + hide_verbose_canvas_cursor() ; + + /* no x or y movement either means the regionview hasn't been moved, or has been moved + but is back in it's original position/trackview.*/ + + if(!item_x_movement && event && event->type == GDK_BUTTON_RELEASE) + { + /* No motion: either set the current region, or align the clicked region + with the current one. + */ + return; + } + + if(item_x_movement) + { + /* base the new region position on the current position of the regionview.*/ + where = drag_info.current_pointer_frame ; + + // final call to set position after the motion to tell interested parties of the new position + tavi->set_position(where, this) ; + } + else + { + //where = tavi->get_position() ; + } + + +} + + +void +Editor::imageframe_start_handle_op(GtkCanvasItem* item, GdkEvent* event) +{ + // get the selected item from the parent time axis + ImageFrameTimeAxis* ifta = dynamic_cast(clicked_trackview) ; + if(ifta) + { + ImageFrameView* ifv = ifta->get_view()->get_selected_imageframe_view() ; + + if (ifv == 0) { + fatal << _("programming error: no ImageFrameView selected") << endmsg; + /*NOTREACHED*/ + return ; + } + + drag_info.item = ifv->get_canvas_frame() ; + drag_info.data = ifv; + drag_info.grab_x = event->motion.x; + drag_info.cumulative_x_drag = 0; + drag_info.motion_callback = &Editor::imageframe_start_handle_trim_motion ; + drag_info.finished_callback = &Editor::imageframe_start_handle_end_trim ; + + flush_track_canvas() ; + + start_grab(event) ; + + show_verbose_time_cursor(ifv->get_position(), 10) ; + } +} + +void +Editor::imageframe_end_handle_op(GtkCanvasItem* item, GdkEvent* event) +{ + // get the selected item from the parent time axis + ImageFrameTimeAxis* ifta = dynamic_cast(clicked_trackview) ; + + if(ifta) + { + ImageFrameView* ifv = ifta->get_view()->get_selected_imageframe_view() ; + + if (ifv == 0) + { + fatal << _("programming error: no ImageFrameView selected") << endmsg ; + /*NOTREACHED*/ + return ; + } + + drag_info.item = ifv->get_canvas_frame() ; + drag_info.data = ifv ; + drag_info.grab_x = event->motion.x ; + drag_info.cumulative_x_drag = 0 ; + drag_info.motion_callback = &Editor::imageframe_end_handle_trim_motion ; + drag_info.finished_callback = &Editor::imageframe_end_handle_end_trim ; + + flush_track_canvas() ; + + start_grab(event, trimmer_cursor) ; + + show_verbose_time_cursor(ifv->get_position() + ifv->get_duration(), 10) ; + } +} + +void +Editor::imageframe_start_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event) +{ + ImageFrameView* ifv = reinterpret_cast (drag_info.data) ; + + jack_nframes_t start = 0 ; + jack_nframes_t end = 0 ; + jack_nframes_t pointer_frame = event_frame(event) ; + + // chekc th eposition of the item is not locked + if(!ifv->get_position_locked()) { + snap_to(pointer_frame) ; + + if(pointer_frame != drag_info.last_pointer_frame) { + start = ifv->get_position() ; + end = ifv->get_position() + ifv->get_duration() ; + + if (pointer_frame > end) { + start = end ; + } else { + start = pointer_frame ; + } + + // are we getting bigger or smaller? + jack_nframes_t new_dur_val = end - start ; + + // start handle, so a smaller pointer frame increases our component size + if(pointer_frame <= drag_info.grab_frame) + { + if(ifv->get_max_duration_active() && (new_dur_val > ifv->get_max_duration())) + { + new_dur_val = ifv->get_max_duration() ; + start = end - new_dur_val ; + } + else + { + // current values are ok + } + } + else + { + if(ifv->get_min_duration_active() && (new_dur_val < ifv->get_min_duration())) + { + new_dur_val = ifv->get_min_duration() ; + start = end - new_dur_val ; + } + else + { + // current values are ok + } + } + + drag_info.last_pointer_frame = pointer_frame ; + + /* re-calculatethe duration and position of the imageframeview */ + drag_info.cumulative_x_drag = new_dur_val ; + + // we treat this as a special case, usually we want to send the identitiy of the caller + // but in this case, that would trigger our socket handler to handle the event, sending + // notification to the image compositor. This would be fine, except that we have not + // finished the drag, we therefore do not want to sent notification until we have + // completed the drag, only then do we want the image compositor notofied. + // We therefore set the caller identity to the special case of 0 + ifv->set_duration(new_dur_val, 0) ; + ifv->set_position(start, 0) ; + } + } + + show_verbose_time_cursor(start, 10) ; +} + +void +Editor::imageframe_start_handle_end_trim(GtkCanvasItem* item, GdkEvent* event) +{ + ImageFrameView* ifv = reinterpret_cast (drag_info.data) ; + + if (drag_info.cumulative_x_drag == 0) + { + /* just a click */ + } + else + { + jack_nframes_t temp = ifv->get_position() + ifv->get_duration() ; + + ifv->set_position((jack_nframes_t) (temp - drag_info.cumulative_x_drag), this) ; + ifv->set_duration((jack_nframes_t) drag_info.cumulative_x_drag, this) ; + } + + flush_track_canvas() ; +} + +void +Editor::imageframe_end_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event) +{ + ImageFrameView* ifv = reinterpret_cast (drag_info.data) ; + + jack_nframes_t start = 0 ; + jack_nframes_t end = 0 ; + jack_nframes_t pointer_frame = event_frame(event) ; + jack_nframes_t new_dur_val = 0 ; + + snap_to(pointer_frame) ; + + if (pointer_frame != drag_info.last_pointer_frame) + { + start = ifv->get_position() ; + end = ifv->get_position() + ifv->get_duration() ; + if (pointer_frame < start) + { + end = start ; + } + else + { + end = pointer_frame ; + } + + new_dur_val = end - start ; + + // are we getting bigger or smaller? + if(pointer_frame >= drag_info.last_pointer_frame) + { + if(ifv->get_max_duration_active() && (new_dur_val > ifv->get_max_duration())) + { + new_dur_val = ifv->get_max_duration() ; + } + } + else + { + if(ifv->get_min_duration_active() && (new_dur_val < ifv->get_min_duration())) + { + new_dur_val = ifv->get_min_duration() ; + } + } + + drag_info.last_pointer_frame = pointer_frame ; + drag_info.cumulative_x_drag = new_dur_val ; + + // we treat this as a special case, usually we want to send the identitiy of the caller + // but in this case, that would trigger our socket handler to handle the event, sending + // notification to the image compositor. This would be fine, except that we have not + // finished the drag, we therefore do not want to sent notification until we have + // completed the drag, only then do we want the image compositor notofied. + // We therefore set the caller identity to the special case of 0 + ifv->set_duration(new_dur_val, 0) ; + } + + show_verbose_time_cursor(new_dur_val, 10) ; +} + + +void +Editor::imageframe_end_handle_end_trim (GtkCanvasItem* item, GdkEvent* event) +{ + ImageFrameView* ifv = reinterpret_cast (drag_info.data) ; + + if (drag_info.cumulative_x_drag == 0) + { + /* just a click */ + } + else + { + jack_nframes_t new_duration = (jack_nframes_t)drag_info.cumulative_x_drag ; + if((new_duration <= ifv->get_max_duration()) && (new_duration >= ifv->get_min_duration())) + { + ifv->set_duration(new_duration, this) ; + } + } + + flush_track_canvas (); +} + + +void +Editor::markerview_item_start_handle_op(GtkCanvasItem* item, GdkEvent* event) +{ + MarkerView* mv = reinterpret_cast(clicked_trackview)->get_view()->get_selected_time_axis_item() ; + + if (mv == 0) + { + fatal << _("programming error: no MarkerView selected") << endmsg ; + /*NOTREACHED*/ + return ; + } + + drag_info.item = mv->get_canvas_frame() ; + drag_info.data = mv; + drag_info.grab_x = event->motion.x; + + drag_info.cumulative_x_drag = 0 ; + drag_info.motion_callback = &Editor::markerview_start_handle_trim_motion ; + drag_info.finished_callback = &Editor::markerview_start_handle_end_trim ; + + flush_track_canvas() ; + + start_grab(event, trimmer_cursor) ; +} + +void +Editor::markerview_item_end_handle_op(GtkCanvasItem* item, GdkEvent* event) +{ + MarkerView* mv = reinterpret_cast(clicked_trackview)->get_view()->get_selected_time_axis_item() ; + if (mv == 0) + { + fatal << _("programming error: no MarkerView selected") << endmsg ; + /*NOTREACHED*/ + return ; + } + + drag_info.item = mv->get_canvas_frame() ; + drag_info.data = mv ; + drag_info.grab_x = event->motion.x ; + drag_info.cumulative_x_drag = 0 ; + + drag_info.motion_callback = &Editor::markerview_end_handle_trim_motion ; + drag_info.finished_callback = &Editor::markerview_end_handle_end_trim ; + + flush_track_canvas () ; + + start_grab(event, trimmer_cursor) ; +} + + +void +Editor::markerview_start_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event) +{ + MarkerView* mv = reinterpret_cast (drag_info.data) ; + + jack_nframes_t start = 0 ; + jack_nframes_t end = 0 ; + jack_nframes_t pointer_frame = event_frame(event) ; + + // chekc th eposition of the item is not locked + if(!mv->get_position_locked()) + { + snap_to(pointer_frame) ; + if(pointer_frame != drag_info.last_pointer_frame) + { + start = mv->get_position() ; + end = mv->get_position() + mv->get_duration() ; + + if (pointer_frame > end) + { + start = end ; + } + else + { + start = pointer_frame ; + } + + // are we getting bigger or smaller? + jack_nframes_t new_dur_val = end - start ; + + if(pointer_frame <= drag_info.grab_frame) + { + if(mv->get_max_duration_active() && (new_dur_val > mv->get_max_duration())) + { + new_dur_val = mv->get_max_duration() ; + start = end - new_dur_val ; + } + else + { + // current values are ok + } + } + else + { + if(mv->get_min_duration_active() && (new_dur_val < mv->get_min_duration())) + { + new_dur_val = mv->get_min_duration() ; + start = end - new_dur_val ; + } + else + { + // current values are ok + } + } + + drag_info.last_pointer_frame = pointer_frame ; + + /* re-calculatethe duration and position of the imageframeview */ + drag_info.cumulative_x_drag = new_dur_val ; + + // we treat this as a special case, usually we want to send the identitiy of the caller + // but in this case, that would trigger our socket handler to handle the event, sending + // notification to the image compositor. This would be fine, except that we have not + // finished the drag, we therefore do not want to sent notification until we have + // completed the drag, only then do we want the image compositor notofied. + // We therefore set the caller identity to the special case of 0 + mv->set_duration(new_dur_val, 0) ; + mv->set_position(start, 0) ; + } + } + + show_verbose_time_cursor(start, 10) ; +} + +void +Editor::markerview_start_handle_end_trim(GtkCanvasItem* item, GdkEvent* event) +{ + MarkerView* mv = reinterpret_cast (drag_info.data) ; + + if (drag_info.cumulative_x_drag == 0) + { + /* just a click */ + } + else + { + jack_nframes_t temp = mv->get_position() + mv->get_duration() ; + + mv->set_position((jack_nframes_t) (temp - drag_info.cumulative_x_drag), this) ; + mv->set_duration((jack_nframes_t) drag_info.cumulative_x_drag, this) ; + } + + flush_track_canvas() ; +} + +void +Editor::markerview_end_handle_trim_motion(GtkCanvasItem* item, GdkEvent* event) +{ + MarkerView* mv = reinterpret_cast (drag_info.data) ; + + jack_nframes_t start = 0 ; + jack_nframes_t end = 0 ; + jack_nframes_t pointer_frame = event_frame(event) ; + jack_nframes_t new_dur_val = 0 ; + + snap_to(pointer_frame) ; + + if (pointer_frame != drag_info.last_pointer_frame) + { + start = mv->get_position() ; + end = mv->get_position() + mv->get_duration() ; + + if(pointer_frame < start) + { + end = start ; + } + else + { + end = pointer_frame ; + } + + new_dur_val = end - start ; + + // are we getting bigger or smaller? + if(pointer_frame >= drag_info.last_pointer_frame) + { + // we cant extend beyond the item we are marking + ImageFrameView* marked_item = mv->get_marked_item() ; + jack_nframes_t marked_end = marked_item->get_position() + marked_item->get_duration() ; + + if(mv->get_max_duration_active() && (new_dur_val > mv->get_max_duration())) + { + if((start + mv->get_max_duration()) > marked_end) + { + new_dur_val = marked_end - start ; + } + else + { + new_dur_val = mv->get_max_duration() ; + } + } + else if(end > marked_end) + { + new_dur_val = marked_end - start ; + } + } + else + { + if(mv->get_min_duration_active() && (new_dur_val < mv->get_min_duration())) + { + new_dur_val = mv->get_min_duration() ; + } + } + + + drag_info.last_pointer_frame = pointer_frame ; + drag_info.cumulative_x_drag = new_dur_val ; + + // we treat this as a special case, usually we want to send the identitiy of the caller + // but in this case, that would trigger our socket handler to handle the event, sending + // notification to the image compositor. This would be fine, except that we have not + // finished the drag, we therefore do not want to sent notification until we have + // completed the drag, only then do we want the image compositor notofied. + // We therefore set the caller identity to the special case of 0 + mv->set_duration(new_dur_val, 0) ; + } + + show_verbose_time_cursor(new_dur_val, 10) ; +} + + +void +Editor::markerview_end_handle_end_trim (GtkCanvasItem* item, GdkEvent* event) +{ + MarkerView* mv = reinterpret_cast (drag_info.data) ; + + if (drag_info.cumulative_x_drag == 0) + { + /* just a click */ + } + else + { + jack_nframes_t new_duration = (jack_nframes_t)drag_info.cumulative_x_drag ; + mv->set_duration(new_duration, this) ; + } + + flush_track_canvas() ; +} + + +/* */ + + + + + + + +/* */ + +void +Editor::handle_new_imageframe_time_axis_view(std::string track_name, void* src) +{ + ImageFrameTimeAxis* iftav ; + iftav = new ImageFrameTimeAxis(track_name, *this, *session, track_canvas) ; + iftav->set_time_axis_name(track_name, this) ; + track_views.push_back(iftav) ; + const gchar *rowdata[1] ; + rowdata[0] = iftav->name().c_str() ; + route_list.rows().push_back(rowdata) ; + route_list.rows().back().set_data(iftav) ; + route_list.rows().back().select() ; + iftav->GoingAway.connect(bind(slot(*this, &Editor::remove_route), (TimeAxisView*)iftav)) ; + iftav->gui_changed.connect(slot(*this, &Editor::handle_gui_changes)) ; +} + +void +Editor::handle_new_imageframe_marker_time_axis_view(std::string track_name, TimeAxisView* marked_track) +{ + MarkerTimeAxis* mta = new MarkerTimeAxis (*this, *this->current_session(), track_canvas, track_name, marked_track) ; + ((ImageFrameTimeAxis*)marked_track)->add_marker_time_axis(mta, this) ; + track_views.push_back(mta) ; + const gchar *rowdata[1] ; + rowdata[0] = mta->name().c_str() ; + route_list.rows().push_back(rowdata) ; + route_list.rows().back().set_data (mta) ; + route_list.rows().back().select() ; + mta->GoingAway.connect(bind(slot (*this, &Editor::remove_route), (TimeAxisView*)mta)) ; + } + + +/* */ diff --git a/gtk2_ardour/editor_keyboard.cc b/gtk2_ardour/editor_keyboard.cc new file mode 100644 index 0000000000..8fb0e64235 --- /dev/null +++ b/gtk2_ardour/editor_keyboard.cc @@ -0,0 +1,144 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include "editor.h" +#include "regionview.h" +#include "selection.h" + +void +Editor::kbd_driver (SigC::Slot1 theslot, bool use_track_canvas, bool use_time_canvas, bool can_select) +{ + gint x, y; + double dx, dy; + GdkEvent ev; + GdkModifierType mask; + Gdk_Window evw (track_canvas->get_window().get_pointer (x, y, mask)); + bool doit = false; + + if (use_track_canvas && gdk_window_get_pointer (track_canvas_event_box.get_window(), + &x, &y, &mask)) { + doit = true; + + } else if (use_time_canvas && gdk_window_get_pointer (time_canvas_event_box.get_window(), + &x, &y, &mask)) { + doit = true; + } + + if (doit) { + + if (entered_regionview && can_select) { + selection->set (entered_regionview); + } + + gtk_canvas_window_to_world (GTK_CANVAS(track_gtk_canvas), x, y, &dx, &dy); + + ev.type = GDK_BUTTON_PRESS; + ev.button.x = dx; + ev.button.y = dy; + ev.button.state = 0; /* XXX correct? */ + + theslot (&ev); + } +} + +void +Editor::kbd_set_playhead_cursor () +{ + kbd_driver (slot (*this, &Editor::set_playhead_cursor), true, true, false); +} + +void +Editor::kbd_set_edit_cursor () +{ + kbd_driver (slot (*this, &Editor::set_edit_cursor), true, true, false); +} + + +void +Editor::kbd_do_split (GdkEvent* ev) +{ + jack_nframes_t where = event_frame (ev); + + if (entered_regionview) { + if (selection->audio_regions.find (entered_regionview) != selection->audio_regions.end()) { + split_regions_at (where, selection->audio_regions); + } else { + AudioRegionSelection s; + s.add (entered_regionview); + split_regions_at (where, s); + } + } +} + +void +Editor::kbd_split () +{ + kbd_driver (slot (*this, &Editor::kbd_do_split), true, true, false); +} + +void +Editor::kbd_do_align (GdkEvent* ev, ARDOUR::RegionPoint what) +{ + align (what); +} + +void +Editor::kbd_align (ARDOUR::RegionPoint what) +{ + kbd_driver (bind (slot (*this, &Editor::kbd_do_align), what)); +} + +void +Editor::kbd_do_align_relative (GdkEvent* ev, ARDOUR::RegionPoint what) +{ + align (what); +} + +void +Editor::kbd_align_relative (ARDOUR::RegionPoint what) +{ + kbd_driver (bind (slot (*this, &Editor::kbd_do_align), what), true, true, false); +} + +void +Editor::kbd_do_brush (GdkEvent *ev) +{ + brush (event_frame (ev, 0, 0)); +} + +void +Editor::kbd_brush () +{ + kbd_driver (slot (*this, &Editor::kbd_do_brush), true, true, false); +} + +void +Editor::kbd_do_audition (GdkEvent *ignored) +{ + audition_selected_region (); +} + +void +Editor::kbd_audition () +{ + kbd_driver (slot (*this, &Editor::kbd_do_audition), true, false, true); +} diff --git a/gtk2_ardour/editor_keys.cc b/gtk2_ardour/editor_keys.cc new file mode 100644 index 0000000000..dbcb2a1e52 --- /dev/null +++ b/gtk2_ardour/editor_keys.cc @@ -0,0 +1,268 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include + +#include + +#include + +#include +#include + +#include "ardour_ui.h" +#include "editor.h" +#include "time_axis_view.h" +#include "regionview.h" +#include "selection.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace SigC; + +void +Editor::install_keybindings () +{ + /* add named actions for the editor */ + + add_action ("toggle-xfades-active", slot (*this, &Editor::toggle_xfades_active)); + + add_action ("playhead-to-next-region-start", bind (slot (*this, &Editor::cursor_to_next_region_point), playhead_cursor, RegionPoint (Start))); + add_action ("playhead-to-next-region-end", bind (slot (*this, &Editor::cursor_to_next_region_point), playhead_cursor, RegionPoint (End))); + add_action ("playhead-to-next-region-sync", bind (slot (*this, &Editor::cursor_to_next_region_point), playhead_cursor, RegionPoint (SyncPoint))); + + add_action ("playhead-to-previous-region-start", bind (slot (*this, &Editor::cursor_to_previous_region_point), playhead_cursor, RegionPoint (Start))); + add_action ("playhead-to-previous-region-end", bind (slot (*this, &Editor::cursor_to_previous_region_point), playhead_cursor, RegionPoint (End))); + add_action ("playhead-to-previous-region-sync", bind (slot (*this, &Editor::cursor_to_previous_region_point), playhead_cursor, RegionPoint (SyncPoint))); + + add_action ("edit-cursor-to-next-region-start", bind (slot (*this, &Editor::cursor_to_next_region_point), edit_cursor, RegionPoint (Start))); + add_action ("edit-cursor-to-next-region-end", bind (slot (*this, &Editor::cursor_to_next_region_point), edit_cursor, RegionPoint (End))); + add_action ("edit-cursor-to-next-region-sync", bind (slot (*this, &Editor::cursor_to_next_region_point), edit_cursor, RegionPoint (SyncPoint))); + + add_action ("edit-cursor-to-previous-region-start", bind (slot (*this, &Editor::cursor_to_previous_region_point), edit_cursor, RegionPoint (Start))); + add_action ("edit-cursor-to-previous-region-end", bind (slot (*this, &Editor::cursor_to_previous_region_point), edit_cursor, RegionPoint (End))); + add_action ("edit-cursor-to-previous-region-sync", bind (slot (*this, &Editor::cursor_to_previous_region_point), edit_cursor, RegionPoint (SyncPoint))); + + add_action ("playhead-to-range-start", bind (slot (*this, &Editor::cursor_to_selection_start), playhead_cursor)); + add_action ("playhead-to-range-end", bind (slot (*this, &Editor::cursor_to_selection_end), playhead_cursor)); + + add_action ("edit-cursor-to-range-start", bind (slot (*this, &Editor::cursor_to_selection_start), edit_cursor)); + add_action ("edit-cursor-to-range-end", bind (slot (*this, &Editor::cursor_to_selection_end), edit_cursor)); + + add_action ("jump-forward-to-mark", slot (*this, &Editor::jump_forward_to_mark)); + add_action ("jump-backward-to-mark", slot (*this, &Editor::jump_backward_to_mark)); + add_action ("add-location-from-playhead", slot (*this, &Editor::add_location_from_playhead_cursor)); + + add_action ("nudge-forward", bind (slot (*this, &Editor::nudge_forward), false)); + add_action ("nudge-next-forward", bind (slot (*this, &Editor::nudge_forward), true)); + add_action ("nudge-backward", bind (slot (*this, &Editor::nudge_backward), false)); + add_action ("nudge-next-backward", bind (slot (*this, &Editor::nudge_backward), true)); + + add_action ("toggle-playback", bind (slot (*this, &Editor::toggle_playback), false)); + add_action ("toggle-playback-forget-capture", bind (slot (*this, &Editor::toggle_playback), true)); + + add_action ("toggle-loop-playback", slot (*this, &Editor::toggle_loop_playback)); + + add_action ("temporal-zoom-out", bind (slot (*this, &Editor::temporal_zoom_step), true)); + add_action ("temporal-zoom-in", bind (slot (*this, &Editor::temporal_zoom_step), false)); + add_action ("zoom-to-session", slot (*this, &Editor::temporal_zoom_session)); + + add_action ("scroll-tracks-up", slot (*this, &Editor::scroll_tracks_up)); + add_action ("scroll-tracks-down", slot (*this, &Editor::scroll_tracks_down)); + add_action ("step-tracks-up", slot (*this, &Editor::scroll_tracks_up_line)); + add_action ("step-tracks-down", slot (*this, &Editor::scroll_tracks_down_line)); + + add_action ("scroll-backward", bind (slot (*this, &Editor::scroll_backward), 0.8f)); + add_action ("scroll-forward", bind (slot (*this, &Editor::scroll_forward), 0.8f)); + add_action ("goto", slot (*this, &Editor::goto_frame)); + add_action ("center-playhead", slot (*this, &Editor::center_playhead)); + add_action ("center-edit_cursor", slot (*this, &Editor::center_edit_cursor)); + add_action ("playhead-forward", slot (*this, &Editor::playhead_forward)); + add_action ("playhead-backward", slot (*this, &Editor::playhead_backward)); + add_action ("playhead-to-edit", bind (slot (*this, &Editor::cursor_align), true)); + add_action ("edit-to-playhead", bind (slot (*this, &Editor::cursor_align), false)); + + add_action ("align-regions-start", bind (slot (*this, &Editor::align), ARDOUR::Start)); + add_action ("align-regions-start-relative", bind (slot (*this, &Editor::align_relative), ARDOUR::Start)); + add_action ("align-regions-end", bind (slot (*this, &Editor::align), ARDOUR::End)); + add_action ("align-regions-end-relative", bind (slot (*this, &Editor::align_relative), ARDOUR::End)); + add_action ("align-regions-sync", bind (slot (*this, &Editor::align), ARDOUR::SyncPoint)); + add_action ("align-regions-sync-relative", bind (slot (*this, &Editor::align_relative), ARDOUR::SyncPoint)); + + add_action ("set-playhead", slot (*this, &Editor::kbd_set_playhead_cursor)); + add_action ("set-edit-cursor", slot (*this, &Editor::kbd_set_edit_cursor)); + + add_action ("set-mouse-mode-object", bind (slot (*this, &Editor::set_mouse_mode), Editing::MouseObject, false)); + add_action ("set-mouse-mode-range", bind (slot (*this, &Editor::set_mouse_mode), Editing::MouseRange, false)); + add_action ("set-mouse-mode-gain", bind (slot (*this, &Editor::set_mouse_mode), Editing::MouseGain, false)); + add_action ("set-mouse-mode-zoom", bind (slot (*this, &Editor::set_mouse_mode), Editing::MouseZoom, false)); + add_action ("set-mouse-mode-timefx", bind (slot (*this, &Editor::set_mouse_mode), Editing::MouseTimeFX, false)); + + add_action ("set-undo", bind (slot (*this, &Editor::undo), 1U)); + add_action ("set-redo", bind (slot (*this, &Editor::redo), 1U)); + + add_action ("export-session", slot (*this, &Editor::export_session)); + add_action ("export-range", slot (*this, &Editor::export_selection)); + + add_action ("editor-cut", slot (*this, &Editor::cut)); + add_action ("editor-copy", slot (*this, &Editor::copy)); + add_action ("editor-paste", slot (*this, &Editor::keyboard_paste)); + add_action ("duplicate-region", slot (*this, &Editor::keyboard_duplicate_region)); + add_action ("duplicate-range", slot (*this, &Editor::keyboard_duplicate_selection)); + add_action ("insert-region", slot (*this, &Editor::keyboard_insert_region_list_selection)); + add_action ("reverse-region", slot (*this, &Editor::reverse_region)); + add_action ("normalize-region", slot (*this, &Editor::normalize_region)); + add_action ("editor-crop", slot (*this, &Editor::crop_region_to_selection)); + add_action ("insert-chunk", bind (slot (*this, &Editor::paste_named_selection), 1.0f)); + + add_action ("split-at-edit-cursor", slot (*this, &Editor::split_region)); + add_action ("split-at-mouse", slot (*this, &Editor::kbd_split)); + + add_action ("brush-at-mouse", slot (*this, &Editor::kbd_brush)); + add_action ("audition-at-mouse", slot (*this, &Editor::kbd_audition)); + + add_action ("start-range", slot (*this, &Editor::keyboard_selection_begin)); + add_action ("finish-range", bind (slot (*this, &Editor::keyboard_selection_finish), false)); + add_action ("finish-add-range", bind (slot (*this, &Editor::keyboard_selection_finish), true)); + + add_action ("extend-range-to-end-of-region", bind (slot (*this, &Editor::extend_selection_to_end_of_region), false)); + add_action ("extend-range-to-start-of-region", bind (slot (*this, &Editor::extend_selection_to_start_of_region), false)); + + add_action ("zoom-focus-left", bind (slot (*this, &Editor::set_zoom_focus), Editing::ZoomFocusLeft)); + add_action ("zoom-focus-right", bind (slot (*this, &Editor::set_zoom_focus), Editing::ZoomFocusRight)); + add_action ("zoom-focus-center", bind (slot (*this, &Editor::set_zoom_focus), Editing::ZoomFocusCenter)); + add_action ("zoom-focus-playhead", bind (slot (*this, &Editor::set_zoom_focus), Editing::ZoomFocusPlayhead)); + add_action ("zoom-focus-edit", bind (slot (*this, &Editor::set_zoom_focus), Editing::ZoomFocusEdit)); + + add_action ("toggle-follow-playhead", (slot (*this, &Editor::toggle_follow_playhead))); + add_action ("remove-last-capture", (slot (*this, &Editor::remove_last_capture))); + + add_action ("snap-to-frame", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToFrame))); + add_action ("snap-to-cd-frame", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToCDFrame))); + add_action ("snap-to-smpte-frame", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToSMPTEFrame))); + add_action ("snap-to-smpte-seconds", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToSMPTESeconds))); + add_action ("snap-to-smpte-minutes", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToSMPTEMinutes))); + add_action ("snap-to-seconds", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToSeconds))); + add_action ("snap-to-minutes", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToMinutes))); + add_action ("snap-to-thirtyseconds", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToAThirtysecondBeat))); + add_action ("snap-to-asixteenthbeat", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToASixteenthBeat))); + add_action ("snap-to-eighths", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToAEighthBeat))); + add_action ("snap-to-quarters", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToAQuarterBeat))); + add_action ("snap-to-thirds", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToAThirdBeat))); + add_action ("snap-to-beat", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToBeat))); + add_action ("snap-to-bar", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToBar))); + add_action ("snap-to-mark", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToMark))); + add_action ("snap-to-edit-cursor", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToEditCursor))); + add_action ("snap-to-region-start", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToRegionStart))); + add_action ("snap-to-region-end", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToRegionEnd))); + add_action ("snap-to-region-sync", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToRegionSync))); + add_action ("snap-to-region-boundary", (bind (slot (*this, &Editor::set_snap_to), Editing::SnapToRegionBoundary))); +} + +void +Editor::keyboard_selection_finish (bool add) +{ + if (session && have_pending_keyboard_selection) { + begin_reversible_command (_("keyboard selection")); + if (!add) { + selection->set (0, pending_keyboard_selection_start, session->audible_frame()); + } else { + selection->add (pending_keyboard_selection_start, session->audible_frame()); + } + commit_reversible_command (); + have_pending_keyboard_selection = false; + } +} + +void +Editor::keyboard_selection_begin () +{ + if (session) { + pending_keyboard_selection_start = session->audible_frame(); + have_pending_keyboard_selection = true; + } +} + +void +Editor::keyboard_duplicate_region () +{ + if (selection->audio_regions.empty()) { + return; + } + + float prefix; + bool was_floating; + + if (get_prefix (prefix, was_floating) == 0) { + duplicate_some_regions (selection->audio_regions, prefix); + } else { + duplicate_some_regions (selection->audio_regions, 1); + } +} + +void +Editor::keyboard_duplicate_selection () +{ + float prefix; + bool was_floating; + + if (get_prefix (prefix, was_floating) == 0) { + duplicate_selection (prefix); + } else { + duplicate_selection (1); + } +} + +void +Editor::keyboard_paste () +{ + float prefix; + bool was_floating; + + if (get_prefix (prefix, was_floating) == 0) { + paste (prefix); + } else { + paste (1); + } +} + +void +Editor::keyboard_insert_region_list_selection () +{ + float prefix; + bool was_floating; + + if (get_prefix (prefix, was_floating) == 0) { + insert_region_list_selection (prefix); + } else { + insert_region_list_selection (1); + } +} + +int +Editor::get_prefix (float& val, bool& was_floating) +{ + return Keyboard::the_keyboard().get_prefix (val, was_floating); +} + diff --git a/gtk2_ardour/editor_markers.cc b/gtk2_ardour/editor_markers.cc new file mode 100644 index 0000000000..54612000d1 --- /dev/null +++ b/gtk2_ardour/editor_markers.cc @@ -0,0 +1,911 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include +#include + +#include + +#include "editor.h" +#include "marker.h" +#include "selection.h" +#include "editing.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace std; +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; + +void +Editor::clear_marker_display () +{ + for (LocationMarkerMap::iterator i = location_markers.begin(); i != location_markers.end(); ++i) { + delete i->second; + } + + location_markers.clear (); +} + +void +Editor::add_new_location (Location *location) +{ + LocationMarkers *lam = new LocationMarkers; + uint32_t color; + + if (location->is_cd_marker()) { + color = location_cd_marker_color; + } else if (location->is_mark()) { + color = location_marker_color; + } else if (location->is_auto_loop()) { + color = location_loop_color; + } else if (location->is_auto_punch()) { + color = location_punch_color; + } else { + color = location_range_color; + } + + if (location->is_mark()) { + lam->start = new Marker (*this, GTK_CANVAS_GROUP(marker_group), color, + location->name(), Marker::Mark, PublicEditor::canvas_marker_event, location->start()); + lam->end = 0; + + } else if (location->is_auto_loop()) { + // transport marker + lam->start = new Marker (*this, GTK_CANVAS_GROUP(transport_marker_group), color, + location->name(), Marker::LoopStart, PublicEditor::canvas_marker_event, location->start()); + lam->end = new Marker (*this, GTK_CANVAS_GROUP(transport_marker_group), color, + location->name(), Marker::LoopEnd, PublicEditor::canvas_marker_event, location->end()); + + } else if (location->is_auto_punch()) { + // transport marker + lam->start = new Marker (*this, GTK_CANVAS_GROUP(transport_marker_group), color, + location->name(), Marker::PunchIn, PublicEditor::canvas_marker_event, location->start()); + lam->end = new Marker (*this, GTK_CANVAS_GROUP(transport_marker_group), color, + location->name(), Marker::PunchOut, PublicEditor::canvas_marker_event, location->end()); + + } else { + + // range marker + lam->start = new Marker (*this, GTK_CANVAS_GROUP(range_marker_group), color, + location->name(), Marker::Start, PublicEditor::canvas_marker_event, location->start()); + lam->end = new Marker (*this, GTK_CANVAS_GROUP(range_marker_group), color, + location->name(), Marker::End, PublicEditor::canvas_marker_event, location->end()); + } + + if (location->is_hidden ()) { + lam->hide(); + } else { + lam->show (); + } + + location->start_changed.connect (slot (*this, &Editor::location_changed)); + location->end_changed.connect (slot (*this, &Editor::location_changed)); + location->changed.connect (slot (*this, &Editor::location_changed)); + location->name_changed.connect (slot (*this, &Editor::location_changed)); + location->FlagsChanged.connect (slot (*this, &Editor::location_flags_changed)); + + pair newpair; + + newpair.first = location; + newpair.second = lam; + + location_markers.insert (newpair); +} + +void +Editor::location_changed (Location *location) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &Editor::location_changed), location)); + + LocationMarkers *lam = find_location_markers (location); + + if (lam == 0) { + /* a location that isn't "marked" with markers */ + return; + } + + lam->set_name (location->name()); + lam->set_position (location->start(), location->end()); + + if (location->is_auto_loop()) { + update_loop_range_view (); + } else if (location->is_auto_punch()) { + update_punch_range_view (); + } +} + +void +Editor::location_flags_changed (Location *location, void *src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Editor::location_flags_changed), location, src)); + + LocationMarkers *lam = find_location_markers (location); + + if (lam == 0) { + /* a location that isn't "marked" with markers */ + return; + } + + if (location->is_cd_marker()) { + lam->set_color_rgba (location_cd_marker_color); + } else if (location->is_mark()) { + lam->set_color_rgba (location_marker_color); + } else if (location->is_auto_punch()) { + lam->set_color_rgba (location_punch_color); + } else if (location->is_auto_loop()) { + lam->set_color_rgba (location_loop_color); + } else { + lam->set_color_rgba (location_range_color); + } + + if (location->is_hidden()) { + lam->hide(); + } else { + lam->show (); + } +} + +Editor::LocationMarkers::~LocationMarkers () +{ + if (start) { + delete start; + } + + if (end) { + delete end; + } +} + +Editor::LocationMarkers * +Editor::find_location_markers (Location *location) +{ + LocationMarkerMap::iterator i; + + for (i = location_markers.begin(); i != location_markers.end(); ++i) { + if ((*i).first == location) { + return (*i).second; + } + } + + return 0; +} + +Location * +Editor::find_location_from_marker (Marker *marker, bool& is_start) +{ + LocationMarkerMap::iterator i; + + for (i = location_markers.begin(); i != location_markers.end(); ++i) { + LocationMarkers *lm = (*i).second; + if (lm->start == marker) { + is_start = true; + return (*i).first; + } else if (lm->end == marker) { + is_start = false; + return (*i).first; + } + } + + return 0; +} + +void +Editor::refresh_location_display_internal (Locations::LocationList& locations) +{ + clear_marker_display (); + + for (Locations::LocationList::iterator i = locations.begin(); i != locations.end(); ++i) { + add_new_location (*i); + } +} + +void +Editor::refresh_location_display () +{ + ENSURE_GUI_THREAD(slot (*this, &Editor::refresh_location_display)); + + if (session) { + session->locations()->apply (*this, &Editor::refresh_location_display_internal); + } +} + +void +Editor::refresh_location_display_s (Change ignored) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Editor::refresh_location_display_s), ignored)); + + if (session) { + session->locations()->apply (*this, &Editor::refresh_location_display_internal); + } +} + +void +Editor::LocationMarkers::hide() +{ + start->hide (); + if (end) { end->hide(); } +} + +void +Editor::LocationMarkers::show() +{ + start->show (); + if (end) { end->show(); } +} + +void +Editor::LocationMarkers::set_name (const string& str) +{ + start->set_name (str); + if (end) { end->set_name (str); } +} + +void +Editor::LocationMarkers::set_position (jack_nframes_t startf, + jack_nframes_t endf) +{ + start->set_position (startf); + if (end) { end->set_position (endf); } +} + +void +Editor::LocationMarkers::set_color_rgba (uint32_t rgba) +{ + start->set_color_rgba (rgba); + if (end) { end->set_color_rgba (rgba); } +} + +void +Editor::mouse_add_new_marker (jack_nframes_t where) +{ + if (session) { + Location *location = new Location (where, where, "mark", Location::IsMark); + session->begin_reversible_command (_("add marker")); + session->add_undo (session->locations()->get_memento()); + session->locations()->add (location, true); + session->add_redo_no_execute (session->locations()->get_memento()); + session->commit_reversible_command (); + } +} + +void +Editor::remove_marker (GtkCanvasItem* item, GdkEvent* event) +{ + Marker* marker; + bool is_start; + + if ((marker = static_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + Location* loc = find_location_from_marker (marker, is_start); + + if (session && loc) { + if (loc->is_end()) { + /* you can't hide or delete this marker */ + return; + } + if (loc->is_auto_loop() || loc->is_auto_punch()) { + // just hide them + loc->set_hidden (true, this); + } + else { + Gtk::Main::idle.connect (bind (slot (*this, &Editor::really_remove_marker), loc)); + } + } +} + +gint +Editor::really_remove_marker (Location* loc) +{ + session->begin_reversible_command (_("remove marker")); + session->add_undo (session->locations()->get_memento()); + session->locations()->remove (loc); + session->add_redo_no_execute (session->locations()->get_memento()); + session->commit_reversible_command (); + return FALSE; +} + +void +Editor::location_gone (Location *location) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Editor::location_gone), location)); + + LocationMarkerMap::iterator i; + + if (location == transport_loop_location()) { + update_loop_range_view (true); + } + + if (location == transport_punch_location()) { + update_punch_range_view (true); + } + + for (i = location_markers.begin(); i != location_markers.end(); ++i) { + if ((*i).first == location) { + delete (*i).second; + location_markers.erase (i); + break; + } + } +} + +void +Editor::tm_marker_context_menu (GdkEventButton* ev, GtkCanvasItem* item) +{ + if (tm_marker_menu == 0) { + build_tm_marker_menu (); + } + + marker_menu_item = item; + tm_marker_menu->popup (1, ev->time); + +} + + +void +Editor::marker_context_menu (GdkEventButton* ev, GtkCanvasItem* item) +{ + Marker * marker; + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + bool is_start; + Location * loc = find_location_from_marker (marker, is_start); + if (loc == transport_loop_location() || loc == transport_punch_location()) { + if (transport_marker_menu == 0) { + build_transport_marker_menu (); + } + marker_menu_item = item; + transport_marker_menu->popup (1, ev->time); + } + else { + if (marker_menu == 0) { + build_marker_menu (); + } + + Menu_Helpers::MenuList & children = marker_menu->items(); + // XXX: should really find this some other way + if (children.size() >= 3) { + MenuItem * loopitem = children[2]; + if (loopitem) { + if (loc->is_mark()) { + loopitem->set_sensitive(false); + } + else { + loopitem->set_sensitive(true); + } + } + } + + marker_menu_item = item; + marker_menu->popup (1, ev->time); + } +} + + +void +Editor::new_transport_marker_context_menu (GdkEventButton* ev, GtkCanvasItem* item) +{ + if (new_transport_marker_menu == 0) { + build_new_transport_marker_menu (); + } + + new_transport_marker_menu->popup (1, ev->time); + +} + +void +Editor::transport_marker_context_menu (GdkEventButton* ev, GtkCanvasItem* item) +{ + if (transport_marker_menu == 0) { + build_transport_marker_menu (); + } + + transport_marker_menu->popup (1, ev->time); +} + +void +Editor::build_marker_menu () +{ + using namespace Menu_Helpers; + + marker_menu = new Menu; + MenuList& items = marker_menu->items(); + marker_menu->set_name ("ArdourContextMenu"); + + items.push_back (MenuElem (_("Locate to"), slot (*this, &Editor::marker_menu_set_playhead))); + items.push_back (MenuElem (_("Play from"), slot (*this, &Editor::marker_menu_play_from))); + items.push_back (MenuElem (_("Loop range"), slot (*this, &Editor::marker_menu_loop_range))); + items.push_back (MenuElem (_("Set from playhead"), slot (*this, &Editor::marker_menu_set_from_playhead))); + items.push_back (MenuElem (_("Set from range"), slot (*this, &Editor::marker_menu_set_from_selection))); + + items.push_back (SeparatorElem()); + + items.push_back (MenuElem (_("Rename"), slot (*this, &Editor::marker_menu_rename))); + items.push_back (MenuElem (_("Hide"), slot (*this, &Editor::marker_menu_hide))); + items.push_back (MenuElem (_("Remove"), slot (*this, &Editor::marker_menu_remove))); +} + +void +Editor::build_tm_marker_menu () +{ + using namespace Menu_Helpers; + + tm_marker_menu = new Menu; + MenuList& items = tm_marker_menu->items(); + tm_marker_menu->set_name ("ArdourContextMenu"); + + items.push_back (MenuElem (_("Edit"), slot (*this, &Editor::marker_menu_edit))); + items.push_back (MenuElem (_("Remove"), slot (*this, &Editor::marker_menu_remove))); +} + +void +Editor::build_new_transport_marker_menu () +{ + using namespace Menu_Helpers; + + new_transport_marker_menu = new Menu; + MenuList& items = new_transport_marker_menu->items(); + new_transport_marker_menu->set_name ("ArdourContextMenu"); + + items.push_back (MenuElem (_("Set Loop Range"), slot (*this, &Editor::new_transport_marker_menu_set_loop))); + items.push_back (MenuElem (_("Set Punch Range"), slot (*this, &Editor::new_transport_marker_menu_set_punch))); + + new_transport_marker_menu->unmap_event.connect ( slot (*this, &Editor::new_transport_marker_menu_popdown)); +} + +void +Editor::build_transport_marker_menu () +{ + using namespace Menu_Helpers; + + transport_marker_menu = new Menu; + MenuList& items = transport_marker_menu->items(); + transport_marker_menu->set_name ("ArdourContextMenu"); + + items.push_back (MenuElem (_("Locate to"), slot (*this, &Editor::marker_menu_set_playhead))); + items.push_back (MenuElem (_("Play from"), slot (*this, &Editor::marker_menu_play_from))); + items.push_back (MenuElem (_("Set from playhead"), slot (*this, &Editor::marker_menu_set_from_playhead))); + items.push_back (MenuElem (_("Set from range"), slot (*this, &Editor::marker_menu_set_from_selection))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Hide"), slot (*this, &Editor::marker_menu_hide))); +} + +void +Editor::marker_menu_hide () +{ + Marker* marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + Location* l; + bool is_start; + + if ((l = find_location_from_marker (marker, is_start)) != 0) { + l->set_hidden (true, this); + } +} + +void +Editor::marker_menu_play_from () +{ + Marker* marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + Location* l; + bool is_start; + + if ((l = find_location_from_marker (marker, is_start)) != 0) { + + if (l->is_mark()) { + session->request_locate (l->start(), true); + } + else { + //session->request_bounded_roll (l->start(), l->end()); + + if (is_start) { + session->request_locate (l->start(), true); + } else { + session->request_locate (l->end(), true); + } + } + } +} + +void +Editor::marker_menu_set_playhead () +{ + Marker* marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + Location* l; + bool is_start; + + if ((l = find_location_from_marker (marker, is_start)) != 0) { + + if (l->is_mark()) { + session->request_locate (l->start(), false); + } + else { + if (is_start) { + session->request_locate (l->start(), false); + } else { + session->request_locate (l->end(), false); + } + } + } +} + +void +Editor::marker_menu_set_from_playhead () +{ + Marker* marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + Location* l; + bool is_start; + + if ((l = find_location_from_marker (marker, is_start)) != 0) { + + if (l->is_mark()) { + l->set_start (session->transport_frame ()); + } + else { + if (is_start) { + l->set_start (session->transport_frame ()); + } else { + l->set_end (session->transport_frame ()); + } + } + } +} + +void +Editor::marker_menu_set_from_selection () +{ + Marker* marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + Location* l; + bool is_start; + + if ((l = find_location_from_marker (marker, is_start)) != 0) { + + if (l->is_mark()) { + // nothing for now + } + else { + + /* if range selection use first to last */ + + if (mouse_mode == Editing::MouseRange) { + if (!selection->time.empty()) { + l->set_start (selection->time.start()); + l->set_end (selection->time.end_frame()); + } + } + else { + if (!selection->audio_regions.empty()) { + l->set_start (selection->audio_regions.start()); + l->set_end (selection->audio_regions.end_frame()); + } + } + } + } +} + +void +Editor::marker_menu_loop_range () +{ + Marker* marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + Location* l; + bool is_start; + + if ((l = find_location_from_marker (marker, is_start)) != 0) { + Location* l2; + if ((l2 = transport_loop_location()) != 0) { + l2->set (l->start(), l->end()); + + // enable looping, reposition and start rolling + session->request_auto_loop(true); + session->request_locate (l2->start(), true); + } + } +} + +void +Editor::marker_menu_edit () +{ + MeterMarker* mm; + TempoMarker* tm; + Marker* marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + if ((mm = dynamic_cast (marker)) != 0) { + edit_meter_section (&mm->meter()); + } else if ((tm = dynamic_cast (marker)) != 0) { + edit_tempo_section (&tm->tempo()); + } else { + fatal << X_("programming erorr: unhandled marker type in Editor::marker_menu_edit") + << endmsg; + /*NOTREACHED*/ + } +} + +void +Editor::marker_menu_remove () +{ + MeterMarker* mm; + TempoMarker* tm; + Marker* marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + if ((mm = dynamic_cast (marker)) != 0) { + remove_meter_marker (marker_menu_item); + } else if ((tm = dynamic_cast (marker)) != 0) { + remove_tempo_marker (marker_menu_item); + } else { + remove_marker (marker_menu_item, (GdkEvent*) 0); + } +} + +void +Editor::marker_menu_rename () +{ + Marker* marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(marker_menu_item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + Location* loc; + bool is_start; + + loc = find_location_from_marker (marker, is_start); + + if (!loc) return; + + Dialog dialog; + Entry entry; + Button ok_button (_("OK")); + Button cancel_button (_("Cancel")); + + if (loc->is_mark()) { + dialog.set_title (_("ardour: rename mark")); + } else { + dialog.set_title (_("ardour: rename range")); + } + + dialog.set_name ("MarkRenameWindow"); + dialog.set_usize (300, -1); + dialog.set_position (GTK_WIN_POS_MOUSE); + dialog.set_modal (true); + + dialog.get_vbox()->set_border_width (10); + dialog.get_vbox()->pack_start (entry); + dialog.get_action_area()->pack_start (ok_button); + dialog.get_action_area()->pack_start (cancel_button); + + entry.set_text (loc->name()); + entry.set_name ("MarkerNameDisplay"); + ok_button.set_name ("EditorGTKButton"); + cancel_button.set_name ("EditorGTKButton"); + + entry.activate.connect (bind (slot (*this, &Editor::finish_sub_event_loop), 1)); + cancel_button.clicked.connect (bind (slot (*this, &Editor::finish_sub_event_loop), -1)); + ok_button.clicked.connect (bind (slot (*this, &Editor::finish_sub_event_loop), 1)); + dialog.delete_event.connect (bind (slot (*this, &Editor::finish_sub_event_loop_on_delete), -1)); + + dialog.show_all (); + entry.grab_focus (); + + run_sub_event_loop (); + + if (sub_event_loop_status == 1) { + + Location* l; + bool is_start; + + if ((l = find_location_from_marker (marker, is_start)) != 0) { + l->set_name (entry.get_text()); + } + } +} + +gint +Editor::new_transport_marker_menu_popdown (GdkEventAny *ev) +{ + // hide rects + gtk_canvas_item_hide (transport_bar_drag_rect); + gtk_canvas_item_hide (range_marker_drag_rect); + + return FALSE; +} + +void +Editor::new_transport_marker_menu_set_loop () +{ + if (!session) return; + + begin_reversible_command (_("set loop range")); + + Location* tll; + + if ((tll = transport_loop_location()) == 0) { + Location* loc = new Location (temp_location->start(), temp_location->end(), _("Loop"), Location::IsAutoLoop); + session->add_undo (session->locations()->get_memento()); + session->locations()->add (loc, true); + session->set_auto_loop_location (loc); + session->add_redo_no_execute (session->locations()->get_memento()); + } + else { + session->add_undo (rettype(bind (slot (*tll, &Location::set), tll->start(), tll->end()))); + session->add_redo (rettype(bind (slot (*tll, &Location::set), temp_location->start(), temp_location->end()))); + tll->set_hidden (false, this); + tll->set (temp_location->start(), temp_location->end()); + } + + commit_reversible_command (); +} + +void +Editor::new_transport_marker_menu_set_punch () +{ + if (!session) return; + + begin_reversible_command (_("set punch range")); + + Location* tpl; + + if ((tpl = transport_punch_location()) == 0) { + tpl = new Location (temp_location->start(), temp_location->end(), _("Punch"), Location::IsAutoPunch); + session->add_undo (session->locations()->get_memento()); + session->locations()->add (tpl, true); + session->set_auto_punch_location (tpl); + session->add_redo_no_execute (session->locations()->get_memento()); + } else { + session->add_undo (rettype(bind (slot (*tpl, &Location::set), tpl->start(), tpl->end()))); + session->add_redo (rettype(bind (slot (*tpl, &Location::set), temp_location->start(), temp_location->end()))); + tpl->set_hidden(false, this); + tpl->set(temp_location->start(), temp_location->end()); + } + + commit_reversible_command (); +} + +void +Editor::update_loop_range_view (bool visibility) +{ + if (session == 0) { + return; + } + + Location* tll; + + if (session->get_auto_loop() && ((tll = transport_loop_location()) != 0)) { + + double x1 = frame_to_pixel (tll->start()); + double x2 = frame_to_pixel (tll->end()); + + gtk_canvas_item_set (transport_loop_range_rect, "x1", x1, "x2", x2, NULL); + + if (visibility) { + gtk_canvas_item_show (transport_loop_range_rect); + } + } + else if (visibility) { + gtk_canvas_item_hide (transport_loop_range_rect); + } +} + +void +Editor::update_punch_range_view (bool visibility) +{ + if (session == 0) { + return; + } + + Location* tpl; + + if ((session->get_punch_in() || session->get_punch_out()) && ((tpl = transport_punch_location()) != 0)) { + + double x1 = frame_to_pixel (tpl->start()); + double x2 = frame_to_pixel (tpl->end()); + + gtk_canvas_item_set (transport_punch_range_rect, "x1", x1, "x2", x2, NULL); + + if (visibility) { + gtk_canvas_item_show (transport_punch_range_rect); + } + } + else if (visibility) { + gtk_canvas_item_hide (transport_punch_range_rect); + } + +// if (session->get_punch_in()) { +// double x = frame_to_pixel (transport_punch_location->start()); +// gtk_canvas_item_set (transport_punchin_line, "x1", x, "x2", x, NULL); + +// if (visibility) { +// gtk_canvas_item_show (transport_punchin_line); +// } +// } +// else if (visibility) { +// gtk_canvas_item_hide (transport_punchin_line); +// } + +// if (session->get_punch_out()) { +// double x = frame_to_pixel (transport_punch_location->end()); + +// gtk_canvas_item_set (transport_punchout_line, "x1", x, "x2", x, NULL); + +// if (visibility) { +// gtk_canvas_item_show (transport_punchout_line); +// } +// } +// else if (visibility) { +// gtk_canvas_item_hide (transport_punchout_line); +// } +} diff --git a/gtk2_ardour/editor_mixer.cc b/gtk2_ardour/editor_mixer.cc new file mode 100644 index 0000000000..b5f2ea6cc1 --- /dev/null +++ b/gtk2_ardour/editor_mixer.cc @@ -0,0 +1,311 @@ +/* + Copyright (C) 2003-2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include "editor.h" +#include "mixer_strip.h" +#include "ardour_ui.h" +#include "selection.h" +#include "audio_time_axis.h" + +#include "i18n.h" + +void +Editor::editor_mixer_button_toggled () +{ + show_editor_mixer (editor_mixer_button.get_active()); +} + +void +Editor::cms_deleted () +{ + current_mixer_strip = 0; +} + +void +Editor::show_editor_mixer (bool yn) +{ + if (yn) { + + if (current_mixer_strip == 0) { + + if (selection->tracks.empty()) { + + if (track_views.empty()) { + return; + } + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast (*i)) != 0) { + + current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(), + *session, + atv->route(), false); + + current_mixer_strip->GoingAway.connect (slot (*this, &Editor::cms_deleted)); + break; + } + } + + } else { + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast (*i)) != 0) { + + current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(), + *session, + atv->route(), false); + current_mixer_strip->GoingAway.connect (slot (*this, &Editor::cms_deleted)); + break; + } + } + + } + + if (current_mixer_strip == 0) { + return; + } + } + + if (current_mixer_strip->get_parent() == 0) { + + current_mixer_strip->set_embedded (true); + current_mixer_strip->Hiding.connect (slot (*this, &Editor::current_mixer_strip_hidden)); + current_mixer_strip->GoingAway.connect (slot (*this, &Editor::current_mixer_strip_removed)); + current_mixer_strip->set_width (editor_mixer_strip_width); + current_mixer_strip->show_all (); + + global_hpacker.pack_start (*current_mixer_strip, false, false); + global_hpacker.reorder_child (*current_mixer_strip, 0); + } + + } else { + + if (current_mixer_strip) { + editor_mixer_strip_width = current_mixer_strip->get_width (); + if (current_mixer_strip->get_parent() != 0) { + global_hpacker.remove (*current_mixer_strip); + } + } + } +} + +void +Editor::set_selected_mixer_strip (TimeAxisView& view) +{ + AudioTimeAxisView* at; + bool show = false; + + if (!session || (at = dynamic_cast(&view)) == 0) { + return; + } + + if (current_mixer_strip) { + + /* might be nothing to do */ + + if (¤t_mixer_strip->route() == &at->route()) { + return; + } + + if (current_mixer_strip->get_parent()) { + show = true; + } + + delete current_mixer_strip; + current_mixer_strip = 0; + } + + current_mixer_strip = new MixerStrip (*ARDOUR_UI::instance()->the_mixer(), + *session, + at->route()); + current_mixer_strip->GoingAway.connect (slot (*this, &Editor::cms_deleted)); + + if (show) { + show_editor_mixer (true); + } +} + +void +Editor::update_current_screen () +{ + if (session && engine.running()) { + + jack_nframes_t frame; + + frame = session->audible_frame(); + + /* only update if the playhead is on screen or we are following it */ + + if (_follow_playhead) { + + gtk_canvas_item_show (playhead_cursor->canvas_item); + + if (frame != last_update_frame) { + + if (frame < leftmost_frame || frame > leftmost_frame + current_page_frames()) { + + if (session->transport_speed() < 0) { + if (frame > (current_page_frames()/2)) { + center_screen (frame-(current_page_frames()/2)); + } else { + center_screen (current_page_frames()/2); + } + } else { + center_screen (frame+(current_page_frames()/2)); + } + } + + playhead_cursor->set_position (frame); + } + + } else { + + if (frame != last_update_frame) { + if (frame < leftmost_frame || frame > leftmost_frame + current_page_frames()) { + gtk_canvas_item_hide (playhead_cursor->canvas_item); + } else { + playhead_cursor->set_position (frame); + } + } + } + + last_update_frame = frame; + + if (current_mixer_strip) { + current_mixer_strip->fast_update (); + } + + } +} + +void +Editor::update_slower () +{ + if (current_mixer_strip) { + current_mixer_strip->update (); + } +} + +void +Editor::current_mixer_strip_removed () +{ + if (current_mixer_strip) { + /* it is being deleted */ + current_mixer_strip = 0; + } +} + +void +Editor::current_mixer_strip_hidden () +{ + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + + AudioTimeAxisView* tmp; + + if ((tmp = dynamic_cast(*i)) != 0) { + if (&(tmp->route()) == &(current_mixer_strip->route())) { + (*i)->set_selected (false); + break; + } + } + } + global_hpacker.remove (*current_mixer_strip); +} + +void +Editor::session_going_away () +{ + for (vector::iterator i = session_connections.begin(); i != session_connections.end(); ++i) { + (*i).disconnect (); + } + + stop_scrolling (); + selection->clear (); + cut_buffer->clear (); + + clicked_regionview = 0; + clicked_trackview = 0; + clicked_audio_trackview = 0; + clicked_crossfadeview = 0; + entered_regionview = 0; + entered_track = 0; + latest_regionview = 0; + region_list_display_drag_region = 0; + last_update_frame = 0; + drag_info.item = 0; + last_audition_region = 0; + region_list_button_region = 0; + + /* hide all tracks */ + + hide_all_tracks (false); + + /* rip everything out of the list displays */ + + region_list_clear (); // no clear() method in gtkmm 1.2 + route_list.clear (); + named_selection_display.clear (); + edit_group_list.clear (); + + edit_cursor_clock.set_session (0); + selection_start_clock.set_session (0); + selection_end_clock.set_session (0); + zoom_range_clock.set_session (0); + nudge_clock.set_session (0); + + /* put editor/mixer toggle button in off position and disable until a new session is loaded */ + + editor_mixer_button.set_active(false); + editor_mixer_button.set_sensitive(false); + /* clear tempo/meter rulers */ + + remove_metric_marks (); + hide_measures (); + clear_marker_display (); + + if (current_bbt_points) { + delete current_bbt_points; + current_bbt_points = 0; + } + + if (embed_audio_item) { + embed_audio_item->set_sensitive (false); + } + + if (import_audio_item) { + import_audio_item->set_sensitive (false); + } + + /* mixer strip will be deleted all by itself + when its route is deleted. + */ + + current_mixer_strip = 0; + + set_title (_("ardour: editor")); + + session = 0; +} diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc new file mode 100644 index 0000000000..2c0d90f703 --- /dev/null +++ b/gtk2_ardour/editor_mouse.cc @@ -0,0 +1,4584 @@ +/* + Copyright (C) 2000-2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "ardour_ui.h" +#include "editor.h" +#include "time_axis_view.h" +#include "audio_time_axis.h" +#include "regionview.h" +#include "marker.h" +#include "streamview.h" +#include "region_gain_line.h" +#include "automation_time_axis.h" +#include "prompter.h" +#include "utils.h" +#include "selection.h" +#include "keyboard.h" +#include "editing.h" +#include "rgb_macros.h" +#include "extra_bind.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; +using namespace SigC; +using namespace Gtk; +using namespace Editing; + +jack_nframes_t +Editor::event_frame (GdkEvent* event, double* pcx, double* pcy) +{ + double cx, cy; + + if (pcx == 0) { + pcx = &cx; + } + if (pcy == 0) { + pcy = &cy; + } + + *pcx = 0; + *pcy = 0; + + switch (event->type) { + case GDK_BUTTON_RELEASE: + case GDK_BUTTON_PRESS: + case GDK_2BUTTON_PRESS: + case GDK_3BUTTON_PRESS: + gtk_canvas_w2c_d (GTK_CANVAS(track_gtk_canvas), event->button.x, event->button.y, pcx, pcy); + break; + case GDK_MOTION_NOTIFY: + gtk_canvas_w2c_d (GTK_CANVAS(track_gtk_canvas), event->motion.x, event->motion.y, pcx, pcy); + break; + case GDK_ENTER_NOTIFY: + case GDK_LEAVE_NOTIFY: + gtk_canvas_w2c_d (GTK_CANVAS(track_gtk_canvas), event->crossing.x, event->crossing.y, pcx, pcy); + break; + default: + warning << compose (_("Editor::event_frame() used on unhandled event type %1"), event->type) << endmsg; + break; + } + + /* note that pixel_to_frame() never returns less than zero, so even if the pixel + position is negative (as can be the case with motion events in particular), + the frame location is always positive. + */ + + return pixel_to_frame (*pcx); +} + +void +Editor::mouse_mode_toggled (MouseMode m) +{ + if (ignore_mouse_mode_toggle) { + return; + } + + switch (m) { + case MouseRange: + if (mouse_select_button.get_active()) { + set_mouse_mode (m); + } + break; + + case MouseObject: + if (mouse_move_button.get_active()) { + set_mouse_mode (m); + } + break; + + case MouseGain: + if (mouse_gain_button.get_active()) { + set_mouse_mode (m); + } + break; + + case MouseZoom: + if (mouse_zoom_button.get_active()) { + set_mouse_mode (m); + } + break; + + case MouseTimeFX: + if (mouse_timefx_button.get_active()) { + set_mouse_mode (m); + } + break; + + case MouseAudition: + if (mouse_audition_button.get_active()) { + set_mouse_mode (m); + } + break; + + default: + break; + } +} + +void +Editor::set_mouse_mode (MouseMode m, bool force) +{ + if (drag_info.item) { + return; + } + + if (m == mouse_mode && !force) { + return; + } + + mouse_mode = m; + + instant_save (); + + if (mouse_mode != MouseRange) { + + /* in all modes except range, hide the range selection, + show the object (region) selection. + */ + + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + (*i)->set_should_show_selection (true); + } + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + (*i)->hide_selection (); + } + + } else { + + /* in range mode, hide object (region) selection, and show the + range selection. + */ + + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + (*i)->set_should_show_selection (false); + } + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + if ((*i)->selected()) { + (*i)->show_selection (selection->time); + } + } + } + + /* XXX the hack of unsetting all other buttongs should go + away once GTK2 allows us to use regular radio buttons drawn like + normal buttons, rather than my silly GroupedButton hack. + */ + + ignore_mouse_mode_toggle = true; + + switch (mouse_mode) { + case MouseRange: + mouse_select_button.set_active (true); + current_canvas_cursor = selector_cursor; + break; + + case MouseObject: + mouse_move_button.set_active (true); + current_canvas_cursor = grabber_cursor; + break; + + case MouseGain: + mouse_gain_button.set_active (true); + current_canvas_cursor = cross_hair_cursor; + break; + + case MouseZoom: + mouse_zoom_button.set_active (true); + current_canvas_cursor = zoom_cursor; + break; + + case MouseTimeFX: + mouse_timefx_button.set_active (true); + current_canvas_cursor = time_fx_cursor; // just use playhead + break; + + case MouseAudition: + mouse_audition_button.set_active (true); + current_canvas_cursor = speaker_cursor; + break; + } + + ignore_mouse_mode_toggle = false; + + if (is_drawable()) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); + } +} + +void +Editor::step_mouse_mode (bool next) +{ + switch (current_mouse_mode()) { + case MouseObject: + if (next) set_mouse_mode (MouseRange); + else set_mouse_mode (MouseTimeFX); + break; + + case MouseRange: + if (next) set_mouse_mode (MouseZoom); + else set_mouse_mode (MouseObject); + break; + + case MouseZoom: + if (next) set_mouse_mode (MouseGain); + else set_mouse_mode (MouseRange); + break; + + case MouseGain: + if (next) set_mouse_mode (MouseTimeFX); + else set_mouse_mode (MouseZoom); + break; + + case MouseTimeFX: + if (next) set_mouse_mode (MouseAudition); + else set_mouse_mode (MouseGain); + break; + + case MouseAudition: + if (next) set_mouse_mode (MouseObject); + else set_mouse_mode (MouseTimeFX); + break; + } +} + +gint +Editor::button_press_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) +{ + jack_nframes_t where = event_frame (event, 0, 0); + + if (session && session->actively_recording()) { + return TRUE; + } + + /* in object/audition/timefx mode, any button press sets + the selection if the object can be selected. this is a + bit of hack, because we want to avoid this if the + mouse operation is a region alignment. + */ + + if (((mouse_mode == MouseObject) || + (mouse_mode == MouseAudition && item_type == RegionItem) || + (mouse_mode == MouseTimeFX && item_type == RegionItem)) && + event->type == GDK_BUTTON_PRESS && + event->button.button <= 3) { + + AudioRegionView* rv; + ControlPoint* cp; + + /* not dbl-click or triple-click */ + + switch (item_type) { + case RegionItem: + set_selected_regionview_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true); + break; + + case AudioRegionViewNameHighlight: + case AudioRegionViewName: + if ((rv = reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "regionview"))) != 0) { + set_selected_regionview_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true); + } + break; + + case GainAutomationControlPointItem: + case PanAutomationControlPointItem: + case RedirectAutomationControlPointItem: + if ((cp = reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "control_point"))) != 0) { + set_selected_control_point_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true); + } + break; + + case StreamItem: + break; + + case AutomationTrackItem: + break; + + default: + break; + } + } + +#define SELECT_TRACK_FROM_CANVAS_IN_RANGE_MODE +#ifdef SELECT_TRACK_FROM_CANVAS_IN_RANGE_MODE + /* in range mode, button 1/2/3 press potentially selects a track */ + + if (mouse_mode == MouseRange && + event->type == GDK_BUTTON_PRESS && + event->button.button <= 3) { + + AudioRegionView* rv; + + switch (item_type) { + case StreamItem: + case RegionItem: + case AutomationTrackItem: + set_selected_track_from_click (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift), true, true); + break; + + case AudioRegionViewNameHighlight: + case AudioRegionViewName: + rv = reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "regionview")); + default: + break; + } + } +#endif + + if (drag_info.item == 0 && + (Keyboard::is_delete_event (&event->button) || + Keyboard::is_context_menu_event (&event->button) || + Keyboard::is_edit_event (&event->button))) { + + /* handled by button release */ + return TRUE; + } + + switch (event->button.button) { + case 1: + + if (event->type == GDK_BUTTON_PRESS) { + + if (drag_info.item) { + gtk_canvas_item_ungrab (drag_info.item, event->button.time); + } + + /* single mouse clicks on any of these item types operate + independent of mouse mode, mostly because they are + not on the main track canvas or because we want + them to be modeless. + */ + + switch (item_type) { + case EditCursorItem: + case PlayheadCursorItem: + start_cursor_grab (item, event); + return TRUE; + + case MarkerItem: + if (Keyboard::modifier_state_equals (event->button.state, + Keyboard::ModifierMask(Keyboard::Control|Keyboard::Shift))) { + hide_marker (item, event); + } else { + start_marker_grab (item, event); + } + return TRUE; + + case TempoMarkerItem: + start_tempo_marker_grab (item, event); + return TRUE; + + case MeterMarkerItem: + start_meter_marker_grab (item, event); + return TRUE; + + case TempoBarItem: + return TRUE; + + case MeterBarItem: + return TRUE; + + case RangeMarkerBarItem: + start_range_markerbar_op (item, event, CreateRangeMarker); + return TRUE; + break; + case TransportMarkerBarItem: + start_range_markerbar_op (item, event, CreateTransportMarker); + return TRUE; + break; + + default: + break; + } + } + + switch (mouse_mode) { + case MouseRange: + switch (item_type) { + case StartSelectionTrimItem: + start_selection_op (item, event, SelectionStartTrim); + break; + + case EndSelectionTrimItem: + start_selection_op (item, event, SelectionEndTrim); + break; + + case SelectionItem: + if (Keyboard::modifier_state_contains + (event->button.state, Keyboard::ModifierMask(Keyboard::Alt))) { + // contains and not equals because I can't use alt as a modifier alone. + start_selection_grab (item, event); + } else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) { + /* grab selection for moving */ + start_selection_op (item, event, SelectionMove); + } + else { + /* this was debated, but decided the more common action was to + make a new selection */ + start_selection_op (item, event, CreateSelection); + } + break; + + default: + start_selection_op (item, event, CreateSelection); + } + return TRUE; + break; + + case MouseObject: + if (Keyboard::modifier_state_contains (event->button.state, + Keyboard::ModifierMask(Keyboard::Control|Keyboard::Alt)) + && event->type == GDK_BUTTON_PRESS) { + + start_rubberband_select (item, event); + + } else if (event->type == GDK_BUTTON_PRESS) { + + switch (item_type) { + case FadeInHandleItem: + start_fade_in_grab (item, event); + return TRUE; + + case FadeOutHandleItem: + start_fade_out_grab (item, event); + return TRUE; + + case RegionItem: + if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) { + start_region_copy_grab (item, event); + } else if (Keyboard::the_keyboard().key_is_down (GDK_b)) { + start_region_brush_grab (item, event); + } else { + start_region_grab (item, event); + } + break; + + case AudioRegionViewNameHighlight: + start_trim (item, event); + return TRUE; + break; + + case AudioRegionViewName: + /* rename happens on edit clicks */ + start_trim (clicked_regionview->get_name_highlight(), event); + return TRUE; + break; + + case GainAutomationControlPointItem: + case PanAutomationControlPointItem: + case RedirectAutomationControlPointItem: + start_control_point_grab (item, event); + return TRUE; + break; + + case GainAutomationLineItem: + case PanAutomationLineItem: + case RedirectAutomationLineItem: + start_line_grab_from_line (item, event); + return TRUE; + break; + + case StreamItem: + case AutomationTrackItem: + start_rubberband_select (item, event); + break; + + /* */ + case ImageFrameHandleStartItem: + imageframe_start_handle_op(item, event) ; + return(TRUE) ; + break ; + case ImageFrameHandleEndItem: + imageframe_end_handle_op(item, event) ; + return(TRUE) ; + break ; + case MarkerViewHandleStartItem: + markerview_item_start_handle_op(item, event) ; + return(TRUE) ; + break ; + case MarkerViewHandleEndItem: + markerview_item_end_handle_op(item, event) ; + return(TRUE) ; + break ; + /* */ + + /* */ + case MarkerViewItem: + start_markerview_grab(item, event) ; + break ; + case ImageFrameItem: + start_imageframe_grab(item, event) ; + break ; + /* */ + + default: + break; + } + } + return TRUE; + break; + + case MouseGain: + switch (item_type) { + case RegionItem: + // start_line_grab_from_regionview (item, event); + break; + + case GainControlPointItem: + start_control_point_grab (item, event); + return TRUE; + + case GainLineItem: + start_line_grab_from_line (item, event); + return TRUE; + + case GainAutomationControlPointItem: + case PanAutomationControlPointItem: + case RedirectAutomationControlPointItem: + start_control_point_grab (item, event); + return TRUE; + break; + + default: + break; + } + return TRUE; + break; + + switch (item_type) { + case GainAutomationControlPointItem: + case PanAutomationControlPointItem: + case RedirectAutomationControlPointItem: + start_control_point_grab (item, event); + break; + + case GainAutomationLineItem: + case PanAutomationLineItem: + case RedirectAutomationLineItem: + start_line_grab_from_line (item, event); + break; + + case RegionItem: + // XXX need automation mode to identify which + // line to use + // start_line_grab_from_regionview (item, event); + break; + + default: + break; + } + return TRUE; + break; + + case MouseZoom: + if (event->type == GDK_BUTTON_PRESS) { + start_mouse_zoom (item, event); + } + + return TRUE; + break; + + case MouseTimeFX: + if (item_type == RegionItem) { + start_time_fx (item, event); + } + break; + + case MouseAudition: + /* handled in release */ + break; + + default: + break; + } + break; + + case 2: + switch (mouse_mode) { + case MouseObject: + if (event->type == GDK_BUTTON_PRESS) { + switch (item_type) { + case RegionItem: + if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) { + start_region_copy_grab (item, event); + } else { + start_region_grab (item, event); + } + + break; + case GainAutomationControlPointItem: + case PanAutomationControlPointItem: + case RedirectAutomationControlPointItem: + start_control_point_grab (item, event); + return TRUE; + break; + + default: + break; + } + } + + + switch (item_type) { + case AudioRegionViewNameHighlight: + start_trim (item, event); + return TRUE; + break; + + case AudioRegionViewName: + start_trim (clicked_regionview->get_name_highlight(), event); + return TRUE; + break; + + default: + break; + } + + break; + + case MouseRange: + if (event->type == GDK_BUTTON_PRESS) { + /* relax till release */ + } + return TRUE; + break; + + + case MouseZoom: + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) { + temporal_zoom_session(); + } else { + temporal_zoom_to_frame (true, event_frame(event)); + } + return TRUE; + break; + + default: + break; + } + + break; + + case 3: + break; + + case 4: + switch (mouse_mode) { + case MouseZoom: + //temporal_zoom_to_frame (true, where); + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) { + temporal_zoom_to_frame (true, where); + } + else { + temporal_zoom_step (true); + } + break; + default: + + if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::Alt))) { + scroll_backward (0.6f); + } + else if (Keyboard::no_modifier_keys_pressed (&event->button)) { + scroll_tracks_up_line (); + } else { + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) { + if (clicked_trackview) { + if (!current_stepping_trackview) { + TimeoutSig t; + step_timeout = t.connect (slot (*this, &Editor::track_height_step_timeout), 500); + current_stepping_trackview = clicked_trackview; + } + gettimeofday (&last_track_height_step_timestamp, 0); + current_stepping_trackview->step_height (true); + } + } + else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) { + temporal_zoom_to_frame (true, where); + } + } + } + break; + + case 5: + switch (mouse_mode) { + case MouseZoom: + // temporal_zoom_to_frame (false, where); + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) { + temporal_zoom_to_frame (false, where); + } + else { + temporal_zoom_step (false); + } + break; + default: + + if (Keyboard::modifier_state_contains (event->button.state, Keyboard::ModifierMask(Keyboard::Alt))) { + scroll_forward (0.6f); + } + else if (Keyboard::no_modifier_keys_pressed (&event->button)) { + scroll_tracks_down_line (); + } else { + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) { + if (clicked_trackview) { + if (!current_stepping_trackview) { + TimeoutSig t; + step_timeout = t.connect (slot (*this, &Editor::track_height_step_timeout), 500); + current_stepping_trackview = clicked_trackview; + } + gettimeofday (&last_track_height_step_timestamp, 0); + current_stepping_trackview->step_height (false); + } + } else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) { + temporal_zoom_to_frame (false, where); + } + } + } + break; + + default: + break; + + } + return FALSE; +} + +gint +Editor::button_release_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) +{ + jack_nframes_t where = event_frame (event, 0, 0); + + /* no action if we're recording */ + + if (session && session->actively_recording()) { + return TRUE; + } + + /* first, see if we're finishing a drag ... */ + + if (drag_info.item) { + if (end_grab (item, event)) { + /* grab dragged, so do nothing else */ + return TRUE; + } + } + + /* edit events get handled here */ + + if (drag_info.item == 0 && Keyboard::is_edit_event (&event->button)) { + switch (item_type) { + case RegionItem: + edit_region (); + break; + + case TempoMarkerItem: + edit_tempo_marker (item); + break; + + case MeterMarkerItem: + edit_meter_marker (item); + break; + + case AudioRegionViewName: + if (clicked_regionview->name_active()) { + return mouse_rename_region (item, event); + } + break; + + default: + break; + } + return TRUE; + } + + /* context menu events get handled here */ + + if (Keyboard::is_context_menu_event (&event->button)) { + + if (drag_info.item == 0) { + + /* no matter which button pops up the context menu, tell the menu + widget to use button 1 to drive menu selection. + */ + + switch (item_type) { + case FadeInItem: + case FadeInHandleItem: + case FadeOutItem: + case FadeOutHandleItem: + popup_fade_context_menu (1, event->button.time, item, item_type); + break; + + case StreamItem: + popup_track_context_menu (1, event->button.time, item_type, false, where); + break; + + case RegionItem: + case AudioRegionViewNameHighlight: + case AudioRegionViewName: + popup_track_context_menu (1, event->button.time, item_type, false, where); + break; + + case SelectionItem: + popup_track_context_menu (1, event->button.time, item_type, true, where); + break; + + case AutomationTrackItem: + popup_track_context_menu (1, event->button.time, item_type, false, where); + break; + + case MarkerBarItem: + case RangeMarkerBarItem: + case TransportMarkerBarItem: + case TempoBarItem: + case MeterBarItem: + popup_ruler_menu (pixel_to_frame(event->button.x), item_type); + break; + + case MarkerItem: + marker_context_menu (&event->button, item); + break; + + case TempoMarkerItem: + tm_marker_context_menu (&event->button, item); + break; + + case MeterMarkerItem: + tm_marker_context_menu (&event->button, item); + break; + + case CrossfadeViewItem: + popup_track_context_menu (1, event->button.time, item_type, false, where); + break; + + /* */ + case ImageFrameItem: + popup_imageframe_edit_menu(1, event->button.time, item, true) ; + break ; + case ImageFrameTimeAxisItem: + popup_imageframe_edit_menu(1, event->button.time, item, false) ; + break ; + case MarkerViewItem: + popup_marker_time_axis_edit_menu(1, event->button.time, item, true) ; + break ; + case MarkerTimeAxisItem: + popup_marker_time_axis_edit_menu(1, event->button.time, item, false) ; + break ; + /* */ + + + default: + break; + } + + return TRUE; + } + } + + /* delete events get handled here */ + + if (drag_info.item == 0 && Keyboard::is_delete_event (&event->button)) { + + switch (item_type) { + case TempoMarkerItem: + remove_tempo_marker (item); + break; + + case MeterMarkerItem: + remove_meter_marker (item); + break; + + case MarkerItem: + remove_marker (item, event); + break; + + case RegionItem: + if (mouse_mode == MouseObject) { + remove_clicked_region (); + } + break; + + case GainControlPointItem: + if (mouse_mode == MouseGain) { + remove_gain_control_point (item, event); + } + break; + + case GainAutomationControlPointItem: + case PanAutomationControlPointItem: + case RedirectAutomationControlPointItem: + remove_control_point (item, event); + break; + + default: + break; + } + return TRUE; + } + + switch (event->button.button) { + case 1: + + switch (item_type) { + /* see comments in button_press_handler */ + case EditCursorItem: + case PlayheadCursorItem: + case MarkerItem: + case GainLineItem: + case GainAutomationLineItem: + case PanAutomationLineItem: + case RedirectAutomationLineItem: + case StartSelectionTrimItem: + case EndSelectionTrimItem: + return TRUE; + + case MarkerBarItem: + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (where, 0, true); + } + mouse_add_new_marker (where); + return TRUE; + + case TempoBarItem: + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (where); + } + mouse_add_new_tempo_event (where); + return TRUE; + + case MeterBarItem: + mouse_add_new_meter_event (pixel_to_frame (event->button.x)); + return TRUE; + break; + + default: + break; + } + + switch (mouse_mode) { + case MouseObject: + switch (item_type) { + case AutomationTrackItem: + dynamic_cast(clicked_trackview)->add_automation_event + (item, + event, + where, + event->button.y); + return TRUE; + break; + + default: + break; + } + break; + + case MouseGain: + switch (item_type) { + case RegionItem: + clicked_regionview->add_gain_point_event (item, event); + return TRUE; + break; + + case AutomationTrackItem: + dynamic_cast(clicked_trackview)-> + add_automation_event (item, event, where, event->button.y); + return TRUE; + break; + default: + break; + } + break; + + case MouseAudition: + switch (item_type) { + case RegionItem: + audition_selected_region (); + break; + default: + break; + } + break; + + default: + break; + + } + + return TRUE; + break; + + + case 2: + switch (mouse_mode) { + + case MouseObject: + switch (item_type) { + case RegionItem: + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) { + raise_region (); + } else if (Keyboard::modifier_state_equals (event->button.state, Keyboard::ModifierMask (Keyboard::Shift|Keyboard::Alt))) { + lower_region (); + } else { + // Button2 click is unused + } + return TRUE; + + break; + + default: + break; + } + break; + + case MouseRange: + + // x_style_paste (where, 1.0); + return TRUE; + break; + + default: + break; + } + + break; + + case 3: + break; + + default: + break; + } + return FALSE; +} + +void +Editor::maybe_autoscroll (GdkEvent* event) +{ + jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit); + jack_nframes_t rightmost_frame = leftmost_frame + one_page; + + jack_nframes_t frame = drag_info.current_pointer_frame; + + if (autoscroll_timeout_tag < 0) { + if (frame > rightmost_frame) { + if (rightmost_frame < max_frames) { + start_canvas_autoscroll (1); + } + } else if (frame < leftmost_frame) { + if (leftmost_frame > 0) { + start_canvas_autoscroll (-1); + } + } + } else { + if (frame >= leftmost_frame && frame < rightmost_frame) { + stop_canvas_autoscroll (); + } + } +} + +gint +Editor::enter_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) +{ + ControlPoint* cp; + Marker * marker; + double fraction; + + switch (item_type) { + case GainControlPointItem: + if (mouse_mode == MouseGain) { + cp = reinterpret_cast(gtk_object_get_data (GTK_OBJECT(item), "control_point")); + cp->set_visible (true); + + double at_x, at_y; + at_x = cp->get_x(); + at_y = cp->get_y (); + gtk_canvas_item_i2w (cp->item, &at_x, &at_y); + at_x += 20.0; + at_y += 20.0; + + fraction = 1.0 - (cp->get_y() / cp->line.height()); + + set_verbose_canvas_cursor (cp->line.get_verbose_cursor_string (fraction), at_x, at_y); + show_verbose_canvas_cursor (); + + if (is_drawable()) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), fader_cursor); + } + } + break; + + case GainAutomationControlPointItem: + case PanAutomationControlPointItem: + case RedirectAutomationControlPointItem: + cp = reinterpret_cast(gtk_object_get_data (GTK_OBJECT(item), "control_point")); + cp->set_visible (true); + + double at_x, at_y; + at_x = cp->get_x(); + at_y = cp->get_y (); + gtk_canvas_item_i2w (cp->item, &at_x, &at_y); + at_x += 20.0; + at_y += 20.0; + + fraction = 1.0 - (cp->get_y() / cp->line.height()); + + set_verbose_canvas_cursor (cp->line.get_verbose_cursor_string (fraction), at_x, at_y); + show_verbose_canvas_cursor (); + + if (is_drawable()) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), fader_cursor); + } + break; + + case GainLineItem: + if (mouse_mode == MouseGain) { + gtk_canvas_item_set (item, "fill_color_rgba", color_map[cEnteredGainLine], NULL); + if (is_drawable()) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), fader_cursor); + } + } + break; + + case GainAutomationLineItem: + case RedirectAutomationLineItem: + case PanAutomationLineItem: + gtk_canvas_item_set (item, "fill_color_rgba", color_map[cEnteredAutomationLine], NULL); + if (is_drawable()) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), fader_cursor); + } + break; + + case AudioRegionViewNameHighlight: + if (is_drawable() && mouse_mode == MouseObject) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), trimmer_cursor); + } + break; + + case StartSelectionTrimItem: + case EndSelectionTrimItem: + /* */ + case ImageFrameHandleStartItem: + case ImageFrameHandleEndItem: + case MarkerViewHandleStartItem: + case MarkerViewHandleEndItem: + /* */ + + if (is_drawable()) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), trimmer_cursor); + } + break; + + case EditCursorItem: + case PlayheadCursorItem: + if (is_drawable()) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), grabber_cursor); + } + break; + + case AudioRegionViewName: + + /* when the name is not an active item, the entire name highlight is for trimming */ + + if (!reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "regionview"))->name_active()) { + if (mouse_mode == MouseObject && is_drawable()) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), trimmer_cursor); + } + } + break; + + + case AutomationTrackItem: + if (is_drawable()) { + GdkCursor *cursor; + switch (mouse_mode) { + case MouseRange: + cursor = selector_cursor; + break; + case MouseZoom: + cursor = zoom_cursor; + break; + default: + cursor = cross_hair_cursor; + break; + } + + gdk_window_set_cursor (track_canvas_scroller.get_window(), cursor); + + AutomationTimeAxisView* atv; + if ((atv = static_cast(gtk_object_get_data(GTK_OBJECT(item), "trackview"))) != 0) { + clear_entered_track = false; + set_entered_track (atv); + } + } + break; + + case MarkerBarItem: + case RangeMarkerBarItem: + case TransportMarkerBarItem: + case MeterBarItem: + case TempoBarItem: + if (is_drawable()) { + gdk_window_set_cursor (time_canvas_scroller.get_window(), timebar_cursor); + } + break; + + case MarkerItem: + if ((marker = static_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + break; + } + marker->set_color_rgba (color_map[cEnteredMarker]); + // fall through + case MeterMarkerItem: + case TempoMarkerItem: + if (is_drawable()) { + gdk_window_set_cursor (time_canvas_scroller.get_window(), timebar_cursor); + } + break; + case FadeInHandleItem: + case FadeOutHandleItem: + if (mouse_mode == MouseObject) { + gtk_canvas_item_set (item, "fill_color_rgba", 0, "outline_pixels", 1, NULL); + } + break; + + default: + break; + } + + /* second pass to handle entered track status in a comprehensible way. + */ + + switch (item_type) { + case GainLineItem: + case GainAutomationLineItem: + case RedirectAutomationLineItem: + case PanAutomationLineItem: + case GainControlPointItem: + case GainAutomationControlPointItem: + case PanAutomationControlPointItem: + case RedirectAutomationControlPointItem: + /* these do not affect the current entered track state */ + clear_entered_track = false; + break; + + case AutomationTrackItem: + /* handled above already */ + break; + + default: + set_entered_track (0); + break; + } + + return FALSE; +} + +gint +Editor::leave_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) +{ + AutomationLine* al; + ControlPoint* cp; + Marker *marker; + Location *loc; + AudioRegionView* rv; + bool is_start; + + switch (item_type) { + case GainControlPointItem: + case GainAutomationControlPointItem: + case PanAutomationControlPointItem: + case RedirectAutomationControlPointItem: + cp = reinterpret_cast(gtk_object_get_data (GTK_OBJECT(item), "control_point")); + if (cp->line.npoints() > 1) { + if (!cp->selected) { + cp->set_visible (false); + } + } + + if (is_drawable()) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); + } + + hide_verbose_canvas_cursor (); + break; + + case AudioRegionViewNameHighlight: + case StartSelectionTrimItem: + case EndSelectionTrimItem: + case EditCursorItem: + case PlayheadCursorItem: + /* */ + case ImageFrameHandleStartItem: + case ImageFrameHandleEndItem: + case MarkerViewHandleStartItem: + case MarkerViewHandleEndItem: + /* */ + if (is_drawable()) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); + } + break; + + case GainLineItem: + case GainAutomationLineItem: + case RedirectAutomationLineItem: + case PanAutomationLineItem: + al = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item),"line")); + gtk_canvas_item_set (item, "fill_color_rgba", al->get_line_color(), NULL); + if (is_drawable()) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); + } + break; + + case AudioRegionViewName: + /* see enter_handler() for notes */ + if (!reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "regionview"))->name_active()) { + if (is_drawable() && mouse_mode == MouseObject) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); + } + } + break; + + case RangeMarkerBarItem: + case TransportMarkerBarItem: + case MeterBarItem: + case TempoBarItem: + case MarkerBarItem: + if (is_drawable()) { + gdk_window_set_cursor (time_canvas_scroller.get_window(), timebar_cursor); + } + break; + + case MarkerItem: + if ((marker = static_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + break; + } + loc = find_location_from_marker (marker, is_start); + if (loc) location_flags_changed (loc, this); + // fall through + case MeterMarkerItem: + case TempoMarkerItem: + + if (is_drawable()) { + gdk_window_set_cursor (time_canvas_scroller.get_window(), timebar_cursor); + } + + break; + + case FadeInHandleItem: + case FadeOutHandleItem: + rv = static_cast(gtk_object_get_data (GTK_OBJECT(item), "regionview")); + gtk_canvas_item_set (item, "fill_color_rgba", rv->get_fill_color(), "outline_pixels", 0, NULL); + break; + + case AutomationTrackItem: + if (is_drawable()) { + gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); + + clear_entered_track = true; + Main::idle.connect (slot (*this, &Editor::left_automation_track)); + } + break; + + default: + break; + } + + return FALSE; +} + +gint +Editor::left_automation_track () +{ + if (clear_entered_track) { + set_entered_track (0); + clear_entered_track = false; + } + return FALSE; +} + +gint +Editor::motion_handler (GtkCanvasItem* item, GdkEvent* event, ItemType item_type) +{ + gint x, y; + + /* We call this so that MOTION_NOTIFY events continue to be + delivered to the canvas. We need to do this because we set + GDK_POINTER_MOTION_HINT_MASK on the canvas. This reduces + the density of the events, at the expense of a round-trip + to the server. Given that this will mostly occur on cases + where DISPLAY = :0.0, and given the cost of what the motion + event might do, its a good tradeoff. + */ + + track_canvas->get_pointer (x, y); + + if (current_stepping_trackview) { + /* don't keep the persistent stepped trackview if the mouse moves */ + current_stepping_trackview = 0; + step_timeout.disconnect (); + } + + if (session && session->actively_recording()) { + /* Sorry. no dragging stuff around while we record */ + return TRUE; + } + + drag_info.current_pointer_frame = event_frame (event, &drag_info.current_pointer_x, + &drag_info.current_pointer_y); + if (drag_info.item) { + /* item != 0 is the best test i can think of for + dragging. + */ + if (!drag_info.move_threshold_passsed) + { + drag_info.move_threshold_passsed = (abs ((int) (drag_info.current_pointer_x - drag_info.grab_x)) > 4); + + // and change the initial grab loc/frame if this drag info wants us to + if (drag_info.want_move_threshold && drag_info.move_threshold_passsed) { + drag_info.grab_frame = drag_info.current_pointer_frame; + drag_info.grab_x = drag_info.current_pointer_x; + drag_info.grab_y = drag_info.current_pointer_y; + drag_info.last_pointer_frame = drag_info.grab_frame; + drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; + } + } + } + + switch (item_type) { + case PlayheadCursorItem: + case EditCursorItem: + case MarkerItem: + case GainControlPointItem: + case RedirectAutomationControlPointItem: + case GainAutomationControlPointItem: + case PanAutomationControlPointItem: + case TempoMarkerItem: + case MeterMarkerItem: + case AudioRegionViewNameHighlight: + case StartSelectionTrimItem: + case EndSelectionTrimItem: + case SelectionItem: + case GainLineItem: + case RedirectAutomationLineItem: + case GainAutomationLineItem: + case PanAutomationLineItem: + case FadeInHandleItem: + case FadeOutHandleItem: + /* */ + case ImageFrameHandleStartItem: + case ImageFrameHandleEndItem: + case MarkerViewHandleStartItem: + case MarkerViewHandleEndItem: + /* */ + if (drag_info.item && (event->motion.state & GDK_BUTTON1_MASK || + (event->motion.state & GDK_BUTTON2_MASK))) { + maybe_autoscroll (event); + (this->*(drag_info.motion_callback)) (item, event); + goto handled; + } + goto not_handled; + + default: + break; + } + + switch (mouse_mode) { + case MouseObject: + case MouseRange: + case MouseZoom: + case MouseTimeFX: + if (drag_info.item && (event->motion.state & GDK_BUTTON1_MASK || + (event->motion.state & GDK_BUTTON2_MASK))) { + maybe_autoscroll (event); + (this->*(drag_info.motion_callback)) (item, event); + goto handled; + } + goto not_handled; + break; + + default: + break; + } + + handled: + track_canvas_motion (item, event); + return TRUE; + + not_handled: + return FALSE; +} + +void +Editor::start_grab (GdkEvent* event, GdkCursor *cursor) +{ + if (drag_info.item == 0) { + fatal << _("programming error: start_grab called without drag item") << endmsg; + /*NOTREACHED*/ + return; + } + + if (cursor == 0) { + cursor = grabber_cursor; + } + + // if dragging with button2, the motion is x constrained, with Alt-button2 it is y constrained + + if (event->button.button == 2) { + drag_info.x_constrained = true; + } else { + drag_info.x_constrained = false; + } + + drag_info.grab_frame = event_frame(event, &drag_info.grab_x, &drag_info.grab_y); + drag_info.last_pointer_frame = drag_info.grab_frame; + drag_info.current_pointer_frame = drag_info.grab_frame; + drag_info.current_pointer_x = drag_info.grab_x; + drag_info.current_pointer_y = drag_info.grab_y; + drag_info.cumulative_x_drag = 0; + drag_info.cumulative_y_drag = 0; + drag_info.first_move = true; + drag_info.move_threshold_passsed = false; + drag_info.want_move_threshold = false; + drag_info.pointer_frame_offset = 0; + drag_info.brushing = false; + drag_info.copied_location = 0; + + gtk_canvas_item_grab (drag_info.item, + GDK_POINTER_MOTION_MASK|GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK, + cursor, + event->button.time); + + if (session && session->transport_rolling()) { + drag_info.was_rolling = true; + } else { + drag_info.was_rolling = false; + } + + switch (snap_type) { + case SnapToRegionStart: + case SnapToRegionEnd: + case SnapToRegionSync: + case SnapToRegionBoundary: + build_region_boundary_cache (); + break; + default: + break; + } +} + +bool +Editor::end_grab (GtkCanvasItem* item, GdkEvent* event) +{ + bool did_drag = false; + + stop_canvas_autoscroll (); + + if (drag_info.item == 0) { + return false; + } + + gtk_canvas_item_ungrab (drag_info.item, event->button.time); + + if (drag_info.finished_callback) { + (this->*(drag_info.finished_callback)) (item, event); + } + + did_drag = !drag_info.first_move; + + hide_verbose_canvas_cursor(); + + drag_info.item = 0; + drag_info.copy = false; + drag_info.motion_callback = 0; + drag_info.finished_callback = 0; + drag_info.last_trackview = 0; + drag_info.last_frame_position = 0; + drag_info.grab_frame = 0; + drag_info.last_pointer_frame = 0; + drag_info.current_pointer_frame = 0; + drag_info.brushing = false; + + if (drag_info.copied_location) { + delete drag_info.copied_location; + drag_info.copied_location = 0; + } + + return did_drag; +} + +void +Editor::set_edit_cursor (GdkEvent* event) +{ + jack_nframes_t pointer_frame = event_frame (event); + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + if (snap_type != SnapToEditCursor) { + snap_to (pointer_frame); + } + } + + edit_cursor->set_position (pointer_frame); + edit_cursor_clock.set (pointer_frame); +} + +void +Editor::set_playhead_cursor (GdkEvent* event) +{ + jack_nframes_t pointer_frame = event_frame (event); + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (pointer_frame); + } + + if (session) { + session->request_locate (pointer_frame, session->transport_rolling()); + } +} + +void +Editor::start_fade_in_grab (GtkCanvasItem* item, GdkEvent* event) +{ + drag_info.item = item; + drag_info.motion_callback = &Editor::fade_in_drag_motion_callback; + drag_info.finished_callback = &Editor::fade_in_drag_finished_callback; + + start_grab (event); + + if ((drag_info.data = (gtk_object_get_data (GTK_OBJECT(item), "regionview"))) == 0) { + fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg; + /*NOTREACHED*/ + } + + AudioRegionView* arv = static_cast(drag_info.data); + + drag_info.pointer_frame_offset = drag_info.grab_frame - ((jack_nframes_t) arv->region.fade_in().back()->when + arv->region.position()); +} + +void +Editor::fade_in_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +{ + AudioRegionView* arv = static_cast(drag_info.data); + jack_nframes_t pos; + jack_nframes_t fade_length; + + if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { + pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; + } + else { + pos = 0; + } + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (pos); + } + + if (pos < (arv->region.position() + 64)) { + fade_length = 64; // this should be a minimum defined somewhere + } else if (pos > arv->region.last_frame()) { + fade_length = arv->region.length(); + } else { + fade_length = pos - arv->region.position(); + } + + arv->reset_fade_in_shape_width (fade_length); + + show_verbose_duration_cursor (arv->region.position(), arv->region.position() + fade_length, 10); + + drag_info.first_move = false; +} + +void +Editor::fade_in_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +{ + if (drag_info.first_move) return; + + AudioRegionView* arv = static_cast(drag_info.data); + jack_nframes_t pos; + jack_nframes_t fade_length; + + if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { + pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; + } + else { + pos = 0; + } + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (pos); + } + + if (pos < (arv->region.position() + 64)) { + fade_length = 64; // this should be a minimum defined somewhere + } + else if (pos > arv->region.last_frame()) { + fade_length = arv->region.length(); + } + else { + fade_length = pos - arv->region.position(); + } + + begin_reversible_command (_("change fade in length")); + session->add_undo (arv->region.get_memento()); + arv->region.set_fade_in_length (fade_length); + session->add_redo_no_execute (arv->region.get_memento()); + commit_reversible_command (); + fade_in_drag_motion_callback (item, event); +} + +void +Editor::start_fade_out_grab (GtkCanvasItem* item, GdkEvent* event) +{ + drag_info.item = item; + drag_info.motion_callback = &Editor::fade_out_drag_motion_callback; + drag_info.finished_callback = &Editor::fade_out_drag_finished_callback; + + start_grab (event); + + if ((drag_info.data = (gtk_object_get_data (GTK_OBJECT(item), "regionview"))) == 0) { + fatal << _("programming error: fade out canvas item has no regionview data pointer!") << endmsg; + /*NOTREACHED*/ + } + + AudioRegionView* arv = static_cast(drag_info.data); + + drag_info.pointer_frame_offset = drag_info.grab_frame - (arv->region.length() - (jack_nframes_t) arv->region.fade_out().back()->when + arv->region.position()); +} + +void +Editor::fade_out_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +{ + AudioRegionView* arv = static_cast(drag_info.data); + jack_nframes_t pos; + jack_nframes_t fade_length; + + if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { + pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; + } + else { + pos = 0; + } + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (pos); + } + + if (pos > (arv->region.last_frame() - 64)) { + fade_length = 64; // this should really be a minimum fade defined somewhere + } + else if (pos < arv->region.position()) { + fade_length = arv->region.length(); + } + else { + fade_length = arv->region.last_frame() - pos; + } + + arv->reset_fade_out_shape_width (fade_length); + + show_verbose_duration_cursor (arv->region.last_frame() - fade_length, arv->region.last_frame(), 10); + + drag_info.first_move = false; +} + +void +Editor::fade_out_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +{ + if (drag_info.first_move) return; + + AudioRegionView* arv = static_cast(drag_info.data); + jack_nframes_t pos; + jack_nframes_t fade_length; + + if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { + pos = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; + } + else { + pos = 0; + } + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (pos); + } + + if (pos > (arv->region.last_frame() - 64)) { + fade_length = 64; // this should really be a minimum fade defined somewhere + } + else if (pos < arv->region.position()) { + fade_length = arv->region.length(); + } + else { + fade_length = arv->region.last_frame() - pos; + } + + begin_reversible_command (_("change fade out length")); + session->add_undo (arv->region.get_memento()); + arv->region.set_fade_out_length (fade_length); + session->add_redo_no_execute (arv->region.get_memento()); + commit_reversible_command (); + + fade_out_drag_motion_callback (item, event); +} + +void +Editor::start_cursor_grab (GtkCanvasItem* item, GdkEvent* event) +{ + drag_info.item = item; + drag_info.motion_callback = &Editor::cursor_drag_motion_callback; + drag_info.finished_callback = &Editor::cursor_drag_finished_callback; + + start_grab (event); + + if ((drag_info.data = (gtk_object_get_data (GTK_OBJECT(item), "cursor"))) == 0) { + fatal << _("programming error: cursor canvas item has no cursor data pointer!") << endmsg; + /*NOTREACHED*/ + } + + Cursor* cursor = (Cursor *) drag_info.data; + + if (session && cursor == playhead_cursor) { + if (drag_info.was_rolling) { + session->request_stop (); + } + } + + drag_info.pointer_frame_offset = drag_info.grab_frame - cursor->current_frame; + + show_verbose_time_cursor (cursor->current_frame, 10); +} + +void +Editor::cursor_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +{ + Cursor* cursor = (Cursor *) drag_info.data; + jack_nframes_t adjusted_frame; + + if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { + adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; + } + else { + adjusted_frame = 0; + } + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + if (cursor != edit_cursor || snap_type != SnapToEditCursor) { + snap_to (adjusted_frame); + } + } + + if (adjusted_frame == drag_info.last_pointer_frame) return; + + cursor->set_position (adjusted_frame); + + if (cursor == edit_cursor) { + edit_cursor_clock.set (cursor->current_frame); + } + + show_verbose_time_cursor (cursor->current_frame, 10); + + drag_info.last_pointer_frame = adjusted_frame; + drag_info.first_move = false; +} + +void +Editor::cursor_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +{ + if (drag_info.first_move) return; + + cursor_drag_motion_callback (item, event); + + if (item == playhead_cursor->canvas_item) { + if (session) { + session->request_locate (playhead_cursor->current_frame, drag_info.was_rolling); + } + } else if (item == edit_cursor->canvas_item) { + edit_cursor->set_position (edit_cursor->current_frame); + edit_cursor_clock.set (edit_cursor->current_frame); + } +} + +void +Editor::update_marker_drag_item (Location *location) +{ + double x1 = frame_to_pixel (location->start()); + double x2 = frame_to_pixel (location->end()); + + if (location->is_mark()) { + marker_drag_line_points->coords[0] = x1; + marker_drag_line_points->coords[2] = x1; + gtk_canvas_item_set (marker_drag_line, "points", marker_drag_line_points, NULL); + } + else { + gtk_canvas_item_set (range_marker_drag_rect, "x1", x1, "x2", x2, NULL); + } +} + +void +Editor::start_marker_grab (GtkCanvasItem* item, GdkEvent* event) +{ + Marker* marker; + + if ((marker = static_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + bool is_start; + + Location *location = find_location_from_marker (marker, is_start); + + drag_info.item = item; + drag_info.data = marker; + drag_info.motion_callback = &Editor::marker_drag_motion_callback; + drag_info.finished_callback = &Editor::marker_drag_finished_callback; + + start_grab (event); + + drag_info.copied_location = new Location (*location); + drag_info.pointer_frame_offset = drag_info.grab_frame - (is_start ? location->start() : location->end()); + + update_marker_drag_item (location); + + if (location->is_mark()) { + gtk_canvas_item_show (marker_drag_line); + gtk_canvas_item_raise_to_top (marker_drag_line); + } + else { + gtk_canvas_item_show (range_marker_drag_rect); + gtk_canvas_item_raise_to_top (range_marker_drag_rect); + } + + if (is_start) show_verbose_time_cursor (location->start(), 10); + else show_verbose_time_cursor (location->end(), 10); +} + +void +Editor::marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +{ + jack_nframes_t f_delta; + Marker* marker = (Marker *) drag_info.data; + Location *real_location; + Location *copy_location; + bool is_start; + bool move_both = false; + + jack_nframes_t newframe; + if (drag_info.pointer_frame_offset <= (long) drag_info.current_pointer_frame) { + newframe = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; + } + else { + newframe = 0; + } + + jack_nframes_t next = newframe; + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (newframe, 0, true); + } + + if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) return; + + /* call this to find out if its the start or end */ + + real_location = find_location_from_marker (marker, is_start); + + /* use the copy that we're "dragging" around */ + + copy_location = drag_info.copied_location; + + f_delta = copy_location->end() - copy_location->start(); + + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) { + move_both = true; + } + + if (is_start) { // start marker + + if (move_both) { + copy_location->set_start (newframe); + copy_location->set_end (newframe + f_delta); + } else if (newframe < copy_location->end()) { + copy_location->set_start (newframe); + } else { + snap_to (next, 1, true); + copy_location->set_end (next); + copy_location->set_start (newframe); + } + + } else { // end marker + + if (move_both) { + copy_location->set_end (newframe); + copy_location->set_start (newframe - f_delta); + } else if (newframe > copy_location->start()) { + copy_location->set_end (newframe); + + } else if (newframe > 0) { + snap_to (next, -1, true); + copy_location->set_start (next); + copy_location->set_end (newframe); + } + } + + drag_info.last_pointer_frame = drag_info.current_pointer_frame; + drag_info.first_move = false; + + update_marker_drag_item (copy_location); + + LocationMarkers* lm = find_location_markers (real_location); + lm->set_position (copy_location->start(), copy_location->end()); + + show_verbose_time_cursor (newframe, 10); +} + +void +Editor::marker_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +{ + if (drag_info.first_move) { + marker_drag_motion_callback (item, event); + + } + + Marker* marker = (Marker *) drag_info.data; + bool is_start; + Location * location = find_location_from_marker (marker, is_start); + if (location) { + location->set (drag_info.copied_location->start(), drag_info.copied_location->end()); + } + + gtk_canvas_item_hide (marker_drag_line); + gtk_canvas_item_hide (range_marker_drag_rect); +} + +void +Editor::start_meter_marker_grab (GtkCanvasItem* item, GdkEvent* event) +{ + Marker* marker; + MeterMarker* meter_marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + fatal << _("programming error: meter marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + meter_marker = dynamic_cast (marker); + + MetricSection& section (meter_marker->meter()); + + if (!section.movable()) { + return; + } + + drag_info.item = item; + drag_info.data = marker; + drag_info.motion_callback = &Editor::meter_marker_drag_motion_callback; + drag_info.finished_callback = &Editor::meter_marker_drag_finished_callback; + + start_grab (event); + + drag_info.pointer_frame_offset = drag_info.grab_frame - meter_marker->meter().frame(); + + show_verbose_time_cursor (drag_info.current_pointer_frame, 10); +} + +void +Editor::meter_marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +{ + MeterMarker* marker = (MeterMarker *) drag_info.data; + jack_nframes_t adjusted_frame; + + if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { + adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; + } + else { + adjusted_frame = 0; + } + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (adjusted_frame); + } + + if (adjusted_frame == drag_info.last_pointer_frame) return; + + marker->set_position (adjusted_frame); + + + drag_info.last_pointer_frame = adjusted_frame; + drag_info.first_move = false; + + show_verbose_time_cursor (adjusted_frame, 10); +} + +void +Editor::meter_marker_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +{ + if (drag_info.first_move) return; + + meter_marker_drag_motion_callback (item, event); + + MeterMarker* marker = (MeterMarker *) drag_info.data; + BBT_Time when; + + TempoMap& map (session->tempo_map()); + map.bbt_time (drag_info.last_pointer_frame, when); + + begin_reversible_command (_("move meter mark")); + session->add_undo (map.get_memento()); + map.move_meter (marker->meter(), when); + session->add_redo_no_execute (map.get_memento()); + commit_reversible_command (); +} + +void +Editor::start_tempo_marker_grab (GtkCanvasItem* item, GdkEvent* event) +{ + Marker* marker; + TempoMarker* tempo_marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "tempo_marker"))) == 0) { + fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + if ((tempo_marker = dynamic_cast (marker)) == 0) { + fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg; + /*NOTREACHED*/ + } + + MetricSection& section (tempo_marker->tempo()); + + if (!section.movable()) { + return; + } + + drag_info.item = item; + drag_info.data = marker; + drag_info.motion_callback = &Editor::tempo_marker_drag_motion_callback; + drag_info.finished_callback = &Editor::tempo_marker_drag_finished_callback; + + start_grab (event); + + drag_info.pointer_frame_offset = drag_info.grab_frame - tempo_marker->tempo().frame(); + show_verbose_time_cursor (drag_info.current_pointer_frame, 10); +} + +void +Editor::tempo_marker_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +{ + TempoMarker* marker = (TempoMarker *) drag_info.data; + jack_nframes_t adjusted_frame; + + if ((long)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { + adjusted_frame = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; + } + else { + adjusted_frame = 0; + } + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (adjusted_frame); + } + + if (adjusted_frame == drag_info.last_pointer_frame) return; + + /* OK, we've moved far enough to make it worth actually move the thing. */ + + marker->set_position (adjusted_frame); + + show_verbose_time_cursor (adjusted_frame, 10); + + drag_info.last_pointer_frame = adjusted_frame; + drag_info.first_move = false; +} + +void +Editor::tempo_marker_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +{ + if (drag_info.first_move) return; + + tempo_marker_drag_motion_callback (item, event); + + TempoMarker* marker = (TempoMarker *) drag_info.data; + BBT_Time when; + + TempoMap& map (session->tempo_map()); + map.bbt_time (drag_info.last_pointer_frame, when); + + begin_reversible_command (_("move tempo mark")); + session->add_undo (map.get_memento()); + map.move_tempo (marker->tempo(), when); + session->add_redo_no_execute (map.get_memento()); + commit_reversible_command (); +} + +void +Editor::remove_gain_control_point (GtkCanvasItem*item, GdkEvent* event) +{ + ControlPoint* control_point; + + if ((control_point = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "control_point"))) == 0) { + fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg; + /*NOTREACHED*/ + } + + // We shouldn't remove the first or last gain point + if (control_point->line.is_last_point(*control_point) || + control_point->line.is_first_point(*control_point)) { + return; + } + + control_point->line.remove_point (*control_point); +} + +void +Editor::remove_control_point (GtkCanvasItem*item, GdkEvent* event) +{ + ControlPoint* control_point; + + if ((control_point = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "control_point"))) == 0) { + fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg; + /*NOTREACHED*/ + } + + control_point->line.remove_point (*control_point); +} + +void +Editor::start_control_point_grab (GtkCanvasItem* item, GdkEvent* event) +{ + ControlPoint* control_point; + + if ((control_point = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "control_point"))) == 0) { + fatal << _("programming error: control point canvas item has no control point object pointer!") << endmsg; + /*NOTREACHED*/ + } + + drag_info.item = item; + drag_info.data = control_point; + drag_info.motion_callback = &Editor::control_point_drag_motion_callback; + drag_info.finished_callback = &Editor::control_point_drag_finished_callback; + + start_grab (event, fader_cursor); + + control_point->line.start_drag (control_point, 0); + + float fraction = 1.0 - (control_point->get_y() / control_point->line.height()); + set_verbose_canvas_cursor (control_point->line.get_verbose_cursor_string (fraction), + drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20); + + show_verbose_canvas_cursor (); +} + +void +Editor::control_point_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +{ + ControlPoint* cp = reinterpret_cast (drag_info.data); + + double cx = drag_info.current_pointer_x; + double cy = drag_info.current_pointer_y; + + drag_info.cumulative_x_drag = cx - drag_info.grab_x ; + drag_info.cumulative_y_drag = cy - drag_info.grab_y ; + + bool x_constrained = false; + + if (drag_info.x_constrained) { + if (fabs(drag_info.cumulative_x_drag) < fabs(drag_info.cumulative_y_drag)) { + cx = drag_info.grab_x; + x_constrained = true; + + } else { + cy = drag_info.grab_y; + } + + } + + gtk_canvas_item_w2i (cp->line.parent_group(), &cx, &cy); + + cx = max (0.0, cx); + cy = max (0.0, cy); + cy = min ((double) cp->line.height(), cy); + + //translate cx to frames + jack_nframes_t cx_frames = (jack_nframes_t) floor (cx * frames_per_unit); + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()) && !x_constrained) { + snap_to (cx_frames); + } + + float fraction = 1.0 - (cy / cp->line.height()); + + bool push; + + if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) { + push = true; + } else { + push = false; + } + + cp->line.point_drag (*cp, cx_frames , fraction, push); + + set_verbose_canvas_cursor_text (cp->line.get_verbose_cursor_string (fraction)); +} + +void +Editor::control_point_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +{ + ControlPoint* cp = reinterpret_cast (drag_info.data); + control_point_drag_motion_callback (item, event); + cp->line.end_drag (cp); +} + +void +Editor::start_line_grab_from_regionview (GtkCanvasItem* item, GdkEvent* event) +{ + switch (mouse_mode) { + case MouseGain: + start_line_grab (clicked_regionview->get_gain_line(), event); + break; + default: + break; + } +} + +void +Editor::start_line_grab_from_line (GtkCanvasItem* item, GdkEvent* event) +{ + AutomationLine* al; + + if ((al = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "line"))) == 0) { + fatal << _("programming error: line canvas item has no line pointer!") << endmsg; + /*NOTREACHED*/ + } + + start_line_grab (al, event); +} + +void +Editor::start_line_grab (AutomationLine* line, GdkEvent* event) +{ + double cx; + double cy; + jack_nframes_t frame_within_region; + + /* need to get x coordinate in terms of parent (TimeAxisItemView) + origin. + */ + + cx = event->button.x; + cy = event->button.y; + gtk_canvas_item_w2i (line->parent_group(), &cx, &cy); + frame_within_region = (jack_nframes_t) floor (cx * frames_per_unit); + + if (!line->control_points_adjacent (frame_within_region, current_line_drag_info.before, + current_line_drag_info.after)) { + /* no adjacent points */ + return; + } + + drag_info.item = line->grab_item(); + drag_info.data = line; + drag_info.motion_callback = &Editor::line_drag_motion_callback; + drag_info.finished_callback = &Editor::line_drag_finished_callback; + + start_grab (event, fader_cursor); + + double fraction = 1.0 - (cy / line->height()); + + line->start_drag (0, fraction); + + set_verbose_canvas_cursor (line->get_verbose_cursor_string (fraction), + drag_info.current_pointer_x + 20, drag_info.current_pointer_y + 20); + show_verbose_canvas_cursor (); +} + +void +Editor::line_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +{ + AutomationLine* line = reinterpret_cast (drag_info.data); + double cx = drag_info.current_pointer_x; + double cy = drag_info.current_pointer_y; + + gtk_canvas_item_w2i (line->parent_group(), &cx, &cy); + + double fraction; + fraction = 1.0 - (cy / line->height()); + + bool push; + + if (Keyboard::modifier_state_contains (event->button.state, Keyboard::Control)) { + push = false; + } else { + push = true; + } + + line->line_drag (current_line_drag_info.before, current_line_drag_info.after, fraction, push); + + set_verbose_canvas_cursor_text (line->get_verbose_cursor_string (fraction)); +} + +void +Editor::line_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +{ + AutomationLine* line = reinterpret_cast (drag_info.data); + line_drag_motion_callback (item, event); + line->end_drag (0); +} + +void +Editor::start_region_grab (GtkCanvasItem* item, GdkEvent* event) +{ + if (selection->audio_regions.empty() || clicked_regionview == 0) { + return; + } + + drag_info.copy = false; + drag_info.item = item; + drag_info.data = clicked_regionview; + drag_info.motion_callback = &Editor::region_drag_motion_callback; + drag_info.finished_callback = &Editor::region_drag_finished_callback; + + start_grab (event); + + double speed = 1.0; + TimeAxisView* tvp = clicked_trackview; + AudioTimeAxisView* tv = dynamic_cast(tvp); + + if (tv && tv->is_audio_track()) { + speed = tv->get_diskstream()->speed(); + } + + drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed); + drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; + drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); + // we want a move threshold + drag_info.want_move_threshold = true; + + show_verbose_time_cursor (drag_info.last_frame_position, 10); + + begin_reversible_command (_("move region(s)")); +} + +void +Editor::start_region_copy_grab (GtkCanvasItem* item, GdkEvent* event) +{ + if (selection->audio_regions.empty() || clicked_regionview == 0) { + return; + } + + /* this is committed in the grab finished callback. */ + + begin_reversible_command (_("Drag region copy")); + + /* duplicate the region(s) */ + + vector new_regionviews; + + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + AudioRegionView* rv; + + rv = (*i); + + Playlist* to_playlist = rv->region.playlist(); + AudioTimeAxisView* atv = dynamic_cast(&rv->get_time_axis_view()); + + session->add_undo (to_playlist->get_memento ()); + latest_regionview = 0; + + SigC::Connection c = atv->view->AudioRegionViewAdded.connect (slot (*this, &Editor::collect_new_region_view)); + + /* create a new region with the same name. + */ + + AudioRegion* newregion = new AudioRegion (rv->region); + + /* if the original region was locked, we don't care */ + + newregion->set_locked (false); + + to_playlist->add_region (*newregion, (jack_nframes_t) (rv->region.position() * atv->get_diskstream()->speed())); + + c.disconnect (); + + if (latest_regionview) { + new_regionviews.push_back (latest_regionview); + } + + } + + if (new_regionviews.empty()) { + return; + } + + /* reset selection to new regionviews */ + + selection->set (new_regionviews); + + drag_info.item = new_regionviews.front()->get_canvas_group (); + drag_info.copy = true; + drag_info.data = new_regionviews.front(); + drag_info.motion_callback = &Editor::region_drag_motion_callback; + drag_info.finished_callback = &Editor::region_drag_finished_callback; + + start_grab(event); + + TimeAxisView* tv = &clicked_regionview->get_time_axis_view(); + AudioTimeAxisView* atv = dynamic_cast(tv); + double speed = 1.0; + + if (atv && atv->is_audio_track()) { + speed = atv->get_diskstream()->speed(); + } + + drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); + drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed); + drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; + // we want a move threshold + drag_info.want_move_threshold = true; + + show_verbose_time_cursor (drag_info.last_frame_position, 10); + + begin_reversible_command (_("copy region(s)")); +} + +void +Editor::start_region_brush_grab (GtkCanvasItem* item, GdkEvent* event) +{ + if (selection->audio_regions.empty() || clicked_regionview == 0) { + return; + } + + drag_info.copy = false; + drag_info.item = item; + drag_info.data = clicked_regionview; + drag_info.motion_callback = &Editor::region_drag_motion_callback; + drag_info.finished_callback = &Editor::region_drag_finished_callback; + + start_grab (event); + + double speed = 1.0; + TimeAxisView* tvp = clicked_trackview; + AudioTimeAxisView* tv = dynamic_cast(tvp); + + if (tv && tv->is_audio_track()) { + speed = tv->get_diskstream()->speed(); + } + + drag_info.last_frame_position = (jack_nframes_t) (clicked_regionview->region.position() / speed); + drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; + drag_info.last_trackview = &clicked_regionview->get_time_axis_view(); + // we want a move threshold + drag_info.want_move_threshold = true; + drag_info.brushing = true; + + begin_reversible_command (_("Drag region brush")); +} + +void +Editor::region_drag_motion_callback (GtkCanvasItem* item, GdkEvent* event) +{ + double x_delta; + double y_delta = 0; + AudioRegionView *rv = reinterpret_cast (drag_info.data); + jack_nframes_t pending_region_position = 0; + int32_t pointer_y_span = 0, canvas_pointer_y_span = 0, original_pointer_order; + int32_t visible_y_high = 0, visible_y_low = 512; //high meaning higher numbered.. not the height on the screen + bool clamp_y_axis = false; + vector height_list(512) ; + vector::iterator j; + + /* Which trackview is this ? */ + + TimeAxisView* tvp = trackview_by_y_position (drag_info.current_pointer_y); + AudioTimeAxisView* tv = dynamic_cast(tvp); + + /* The region motion is only processed if the pointer is over + an audio track. + */ + + if (!tv || !tv->is_audio_track()) { + /* To make sure we hide the verbose canvas cursor when the mouse is + not held over and audiotrack. + */ + hide_verbose_canvas_cursor (); + return; + } + + original_pointer_order = drag_info.last_trackview->order; + + /************************************************************ + Y-Delta Computation + ************************************************************/ + + if (drag_info.brushing) { + clamp_y_axis = true; + pointer_y_span = 0; + goto y_axis_done; + } + + if ((pointer_y_span = (drag_info.last_trackview->order - tv->order)) != 0) { + + int32_t children = 0, numtracks = 0; + bitset <512> tracks (0x00); + /* get a bitmask representing the visible tracks */ + + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + TimeAxisView *tracklist_timeview; + tracklist_timeview = (*i); + AudioTimeAxisView* atv2 = dynamic_cast(tracklist_timeview); + list children_list; + + /* zeroes are audio tracks. ones are other types. */ + + if (!atv2->hidden()) { + + if (visible_y_high < atv2->order) { + visible_y_high = atv2->order; + } + if (visible_y_low > atv2->order) { + visible_y_low = atv2->order; + } + + if (!atv2->is_audio_track()) { + tracks = tracks |= (0x01 << atv2->order); + } + + height_list[atv2->order] = (*i)->height; + children = 1; + if ((children_list = atv2->get_child_list()).size() > 0) { + for (list::iterator j = children_list.begin(); j != children_list.end(); ++j) { + tracks = tracks |= (0x01 << (atv2->order + children)); + height_list[atv2->order + children] = (*j)->height; + numtracks++; + children++; + } + } + numtracks++; + } + } + /* find the actual span according to the canvas */ + + canvas_pointer_y_span = pointer_y_span; + if (drag_info.last_trackview->order >= tv->order) { + int32_t y; + for (y = tv->order; y < drag_info.last_trackview->order; y++) { + if (height_list[y] == 0 ) { + canvas_pointer_y_span--; + } + } + } else { + int32_t y; + for (y = drag_info.last_trackview->order;y <= tv->order; y++) { + if ( height_list[y] == 0 ) { + canvas_pointer_y_span++; + } + } + } + + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + AudioRegionView* rv2; + rv2 = (*i); + double ix1, ix2, iy1, iy2; + int32_t n = 0; + + gtk_canvas_item_get_bounds (rv2->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2); + gtk_canvas_item_i2w (rv2->get_canvas_group(), &ix1, &iy1); + TimeAxisView* tvp2 = trackview_by_y_position (iy1); + AudioTimeAxisView* atv2 = dynamic_cast(tvp2); + + if (atv2->order != original_pointer_order) { + /* this isn't the pointer track */ + + if (canvas_pointer_y_span > 0) { + + /* moving up the canvas */ + if ((atv2->order - canvas_pointer_y_span) >= visible_y_low) { + + int32_t visible_tracks = 0; + while (visible_tracks < canvas_pointer_y_span ) { + visible_tracks++; + + while (height_list[atv2->order - (visible_tracks - n)] == 0) { + /* we're passing through a hidden track */ + n--; + } + } + + if (tracks[atv2->order - (canvas_pointer_y_span - n)] != 0x00) { + clamp_y_axis = true; + } + + } else { + clamp_y_axis = true; + } + + } else if (canvas_pointer_y_span < 0) { + + /*moving down the canvas*/ + + if ((atv2->order - (canvas_pointer_y_span - n)) <= visible_y_high) { // we will overflow + + + int32_t visible_tracks = 0; + + while (visible_tracks > canvas_pointer_y_span ) { + visible_tracks--; + + while (height_list[atv2->order - (visible_tracks - n)] == 0) { + n++; + } + } + if ( tracks[atv2->order - ( canvas_pointer_y_span - n)] != 0x00) { + clamp_y_axis = true; + + } + } else { + + clamp_y_axis = true; + } + } + + } else { + + /* this is the pointer's track */ + if ((atv2->order - pointer_y_span) > visible_y_high) { // we will overflow + clamp_y_axis = true; + } else if ((atv2->order - pointer_y_span) < visible_y_low) { // we will underflow + clamp_y_axis = true; + } + } + if (clamp_y_axis) { + break; + } + } + + } else if (drag_info.last_trackview == tv) { + clamp_y_axis = true; + } + + y_axis_done: + if (!clamp_y_axis) { + drag_info.last_trackview = tv; + } + + /************************************************************ + X DELTA COMPUTATION + ************************************************************/ + + /* compute the amount of pointer motion in frames, and where + the region would be if we moved it by that much. + */ + + if (drag_info.move_threshold_passsed) { + + if ((int32_t)drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { + + jack_nframes_t sync_frame; + jack_nframes_t sync_offset; + int32_t sync_dir; + + pending_region_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; + + sync_offset = rv->region.sync_offset (sync_dir); + sync_frame = rv->region.adjust_to_sync (pending_region_position); + + /* we snap if the snap modifier is not enabled. + */ + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (sync_frame); + } + + if (sync_frame - sync_offset <= sync_frame) { + pending_region_position = sync_frame - (sync_dir*sync_offset); + } else { + pending_region_position = 0; + } + + } else { + pending_region_position = 0; + } + + if (pending_region_position > max_frames - rv->region.length()) { + pending_region_position = drag_info.last_frame_position; + } + + // printf ("3: pending_region_position= %lu %lu\n", pending_region_position, drag_info.last_frame_position ); + + if (pending_region_position != drag_info.last_frame_position && !drag_info.x_constrained) { + + /* now compute the canvas unit distance we need to move the regiondrag_info.last_trackview->order + to make it appear at the new location. + */ + + if (pending_region_position > drag_info.last_frame_position) { + x_delta = ((double) (pending_region_position - drag_info.last_frame_position) / frames_per_unit); + } else { + x_delta = -((double) (drag_info.last_frame_position - pending_region_position) / frames_per_unit); + } + + drag_info.last_frame_position = pending_region_position; + + } else { + x_delta = 0; + } + + } else { + /* threshold not passed */ + + x_delta = 0; + } + + /************************************************************* + PREPARE TO MOVE + ************************************************************/ + + if (x_delta == 0 && (pointer_y_span == 0)) { + /* haven't reached next snap point, and we're not switching + trackviews. nothing to do. + */ + return; + } + + if (x_delta < 0) { + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + + AudioRegionView* rv2; + rv2 = (*i); + + /* if any regionview is at zero, we need to know so we can + stop further leftward motion. + */ + + double ix1, ix2, iy1, iy2; + gtk_canvas_item_get_bounds (rv2->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2); + gtk_canvas_item_i2w (rv2->get_canvas_group(), &ix1, &iy1); + + if (ix1 <= 1) { + x_delta = 0; + break; + } + } + } + + /************************************************************* + MOTION + ************************************************************/ + + pair::iterator,bool> insert_result; + + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + + AudioRegionView* rv; + rv = (*i); + double ix1, ix2, iy1, iy2; + int32_t temp_pointer_y_span = pointer_y_span; + + /* get item BBox, which will be relative to parent. so we have + to query on a child, then convert to world coordinates using + the parent. + */ + + gtk_canvas_item_get_bounds (rv->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2); + gtk_canvas_item_i2w (rv->get_canvas_group(), &ix1, &iy1); + TimeAxisView* tvp2 = trackview_by_y_position (iy1); + AudioTimeAxisView* canvas_atv = dynamic_cast(tvp2); + AudioTimeAxisView* temp_atv; + + if ((pointer_y_span != 0) && !clamp_y_axis) { + y_delta = 0; + int32_t x = 0; + for (j = height_list.begin(); j!= height_list.end(); j++) { + if (x == canvas_atv->order) { + /* we found the track the region is on */ + if (x != original_pointer_order) { + /*this isn't from the same track we're dragging from */ + temp_pointer_y_span = canvas_pointer_y_span; + } + while (temp_pointer_y_span > 0) { + /* we're moving up canvas-wise, + so we need to find the next track height + */ + if (j != height_list.begin()) { + j--; + } + if (x != original_pointer_order) { + /* we're not from the dragged track, so ignore hidden tracks. */ + if ((*j) == 0) { + temp_pointer_y_span++; + } + } + y_delta -= (*j); + temp_pointer_y_span--; + } + while (temp_pointer_y_span < 0) { + y_delta += (*j); + if (x != original_pointer_order) { + if ((*j) == 0) { + temp_pointer_y_span--; + } + } + + if (j != height_list.end()) { + j++; + } + temp_pointer_y_span++; + } + /* find out where we'll be when we move and set height accordingly */ + + tvp2 = trackview_by_y_position (iy1 + y_delta); + temp_atv = dynamic_cast(tvp2); + rv->set_height (temp_atv->height); + + /* if you un-comment the following, the region colours will follow the track colours whilst dragging, + personally, i think this can confuse things, but never mind. + */ + + //const GdkColor& col (temp_atv->view->get_region_color()); + //rv->set_color (const_cast(col)); + break; + } + x++; + } + } + + /* prevent the regionview from being moved to before + the zero position on the canvas. + */ + /* clamp */ + + if (x_delta < 0) { + if (-x_delta > ix1) { + x_delta = -ix1; + } + } else if ((x_delta > 0) &&(rv->region.last_frame() > max_frames - x_delta)) { + x_delta = max_frames - rv->region.last_frame(); + } + + if (drag_info.first_move) { + + /* hide any dependent views */ + +// rv->get_time_axis_view().hide_dependent_views (*rv); + + /* this is subtle. raising the regionview itself won't help, + because raise_to_top() just puts the item on the top of + its parent's stack. so, we need to put the trackview canvas_display group + on the top, since its parent is the whole canvas. + */ + + gtk_canvas_item_raise_to_top (rv->get_canvas_group()); + gtk_canvas_item_raise_to_top (rv->get_time_axis_view().canvas_display); + gtk_canvas_item_raise_to_top (cursor_group); + + /* freeze the playlists from notifying till + the motion is done. + */ + + AudioTimeAxisView* atv = dynamic_cast (&rv->get_time_axis_view()); + if (atv && atv->is_audio_track()) { + AudioPlaylist* pl = atv->get_diskstream()->playlist(); + if (pl) { + /* only freeze and capture state once */ + + insert_result = motion_frozen_playlists.insert (pl); + if (insert_result.second) { + pl->freeze(); + session->add_undo(pl->get_memento()); + } + } + } + } + + if (drag_info.brushing) { + mouse_brush_insert_region (rv, pending_region_position); + } else { + rv->move (x_delta, y_delta); + } + } + + if (drag_info.first_move) { + gtk_canvas_item_raise_to_top (cursor_group); + } + + drag_info.first_move = false; + + if (x_delta != 0 && !drag_info.brushing) { + show_verbose_time_cursor (drag_info.last_frame_position, 10); + } + +} + +void +Editor::region_drag_finished_callback (GtkCanvasItem* item, GdkEvent* event) +{ + jack_nframes_t where; + AudioRegionView* rv = reinterpret_cast (drag_info.data); + pair::iterator,bool> insert_result; + bool nocommit = true; + double speed; + AudioTimeAxisView* atv; + bool regionview_y_movement; + bool regionview_x_movement; + + /* first_move is set to false if the regionview has been moved in the + motion handler. + */ + + if (drag_info.first_move) { + /* just a click */ + goto out; + } + + nocommit = false; + + /* The regionview has been moved at some stage during the grab so we need + to account for any mouse movement between this event and the last one. + */ + + region_drag_motion_callback (item, event); + + if (drag_info.brushing) { + /* all changes were made during motion event handlers */ + goto out; + } + + /* adjust for track speed */ + speed = 1.0; + + atv = dynamic_cast (drag_info.last_trackview); + if (atv && atv->get_diskstream()) { + speed = atv->get_diskstream()->speed(); + } + + regionview_x_movement = (drag_info.last_frame_position != (jack_nframes_t) (rv->region.position()/speed)); + regionview_y_movement = (drag_info.last_trackview != &rv->get_time_axis_view()); + + //printf ("last_frame: %s position is %lu %g\n", rv->get_time_axis_view().name().c_str(), drag_info.last_frame_position, speed); + //printf ("last_rackview: %s \n", drag_info.last_trackview->name().c_str()); + + if (regionview_y_movement) { + + /* motion between tracks */ + + list new_selection; + + /* moved to a different audio track. */ + + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ) { + + AudioRegionView* rv2 = (*i); + + /* the region that used to be in the old playlist is not + moved to the new one - we make a copy of it. as a result, + any existing editor for the region should no longer be + visible. + */ + + if (!drag_info.copy) { + rv2->hide_region_editor(); + } + new_selection.push_back (rv2); + i++; + } + + /* first, freeze the target tracks */ + + for (list::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) { + + Playlist* from_playlist; + Playlist* to_playlist; + + double ix1, ix2, iy1, iy2; + + gtk_canvas_item_get_bounds ((*i)->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2); + gtk_canvas_item_i2w ((*i)->get_canvas_group(), &ix1, &iy1); + TimeAxisView* tvp2 = trackview_by_y_position (iy1); + AudioTimeAxisView* atv2 = dynamic_cast(tvp2); + + from_playlist = (*i)->region.playlist(); + to_playlist = atv2->playlist(); + + /* the from_playlist was frozen in the "first_move" case + of the motion handler. the insert can fail, + but that doesn't matter. it just means + we already have the playlist in the list. + */ + + motion_frozen_playlists.insert (from_playlist); + + /* only freeze the to_playlist once */ + + insert_result = motion_frozen_playlists.insert(to_playlist); + if (insert_result.second) { + to_playlist->freeze(); + session->add_undo(to_playlist->get_memento()); + } + + } + + /* now do it again with the actual operations */ + + for (list::const_iterator i = new_selection.begin(); i != new_selection.end();i++ ) { + + Playlist* from_playlist; + Playlist* to_playlist; + + double ix1, ix2, iy1, iy2; + + gtk_canvas_item_get_bounds ((*i)->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2); + gtk_canvas_item_i2w ((*i)->get_canvas_group(), &ix1, &iy1); + TimeAxisView* tvp2 = trackview_by_y_position (iy1); + AudioTimeAxisView* atv2 = dynamic_cast(tvp2); + + from_playlist = (*i)->region.playlist(); + to_playlist = atv2->playlist(); + + latest_regionview = 0; + + where = (jack_nframes_t) (unit_to_frame (ix1) * speed); + Region* new_region = createRegion ((*i)->region); + + from_playlist->remove_region (&((*i)->region)); + + SigC::Connection c = atv2->view->AudioRegionViewAdded.connect (slot (*this, &Editor::collect_new_region_view)); + to_playlist->add_region (*new_region, where); + c.disconnect (); + + if (latest_regionview) { + selection->add (latest_regionview); + } + } + + } else { + + /* motion within a single track */ + + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + + rv = (*i); + + if (rv->region.locked()) { + continue; + } + + if (regionview_x_movement) { + double ownspeed = 1.0; + AudioTimeAxisView* atv = dynamic_cast (&(rv->get_time_axis_view())); + + if (atv && atv->get_diskstream()) { + ownspeed = atv->get_diskstream()->speed(); + } + + /* base the new region position on the current position of the regionview.*/ + + double ix1, ix2, iy1, iy2; + + gtk_canvas_item_get_bounds (rv->get_canvas_frame(), &ix1, &iy1, &ix2, &iy2); + gtk_canvas_item_i2w (rv->get_canvas_group(), &ix1, &iy1); + where = (jack_nframes_t) (unit_to_frame (ix1) * ownspeed); + + } else { + + where = rv->region.position(); + } + + rv->get_time_axis_view().reveal_dependent_views (*rv); + + session->add_undo (rv->region.playlist()->get_memento()); + rv->region.set_position (where, (void *) this); + } + } + + out: + for (set::iterator p = motion_frozen_playlists.begin(); p != motion_frozen_playlists.end(); ++p) { + (*p)->thaw (); + session->add_redo_no_execute ((*p)->get_memento()); + } + + motion_frozen_playlists.clear (); + + if (!nocommit) { + commit_reversible_command (); + } +} + +void +Editor::region_view_item_click (AudioRegionView& rv, GdkEventButton* event) +{ + /* Either add to or set the set the region selection, unless + this is an alignment click (control used) + */ + + if (Keyboard::modifier_state_contains (event->state, Keyboard::Control)) { + TimeAxisView* tv = &rv.get_time_axis_view(); + AudioTimeAxisView* atv = dynamic_cast(tv); + double speed = 1.0; + if (atv && atv->is_audio_track()) { + speed = atv->get_diskstream()->speed(); + } + + if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) { + + align_region (rv.region, SyncPoint, (jack_nframes_t) (edit_cursor->current_frame * speed)); + + } else if (Keyboard::modifier_state_equals (event->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) { + + align_region (rv.region, End, (jack_nframes_t) (edit_cursor->current_frame * speed)); + + } else { + + align_region (rv.region, Start, (jack_nframes_t) (edit_cursor->current_frame * speed)); + } + } +} + +void +Editor::show_verbose_time_cursor (jack_nframes_t frame, double offset, double xpos, double ypos) +{ + char buf[128]; + SMPTE_Time smpte; + BBT_Time bbt; + float secs; + + if (session == 0) { + return; + } + + switch (ARDOUR_UI::instance()->secondary_clock.mode ()) { + case AudioClock::BBT: + session->bbt_time (frame, bbt); + snprintf (buf, sizeof (buf), "%02" PRIu32 "|%02" PRIu32 "|%02" PRIu32, bbt.bars, bbt.beats, bbt.ticks); + break; + + case AudioClock::SMPTE: + session->smpte_time (frame, smpte); + snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%02" PRId32 ":%02" PRId32, smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + break; + + case AudioClock::MinSec: + /* XXX fix this to compute min/sec properly */ + session->smpte_time (frame, smpte); + secs = smpte.seconds + ((float) smpte.frames / session->smpte_frames_per_second); + snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%.4f", smpte.hours, smpte.minutes, secs); + break; + + default: + snprintf (buf, sizeof(buf), "%u", frame); + break; + } + + if (xpos >= 0 && ypos >=0) { + set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset); + } + else { + set_verbose_canvas_cursor (buf, drag_info.current_pointer_x + offset, drag_info.current_pointer_y + offset); + } + show_verbose_canvas_cursor (); +} + +void +Editor::show_verbose_duration_cursor (jack_nframes_t start, jack_nframes_t end, double offset, double xpos, double ypos) +{ + char buf[128]; + SMPTE_Time smpte; + BBT_Time sbbt; + BBT_Time ebbt; + float secs; + Meter meter_at_start(session->tempo_map().meter_at(start)); + + if (session == 0) { + return; + } + + switch (ARDOUR_UI::instance()->secondary_clock.mode ()) { + case AudioClock::BBT: + session->bbt_time (start, sbbt); + session->bbt_time (end, ebbt); + + /* subtract */ + /* XXX this computation won't work well if the + user makes a selection that spans any meter changes. + */ + + ebbt.bars -= sbbt.bars; + if (ebbt.beats >= sbbt.beats) { + ebbt.beats -= sbbt.beats; + } else { + ebbt.bars--; + ebbt.beats = int(meter_at_start.beats_per_bar()) + ebbt.beats - sbbt.beats; + } + if (ebbt.ticks >= sbbt.ticks) { + ebbt.ticks -= sbbt.ticks; + } else { + ebbt.beats--; + ebbt.ticks = int(Meter::ticks_per_beat) + ebbt.ticks - sbbt.ticks; + } + + snprintf (buf, sizeof (buf), "%02" PRIu32 "|%02" PRIu32 "|%02" PRIu32, ebbt.bars, ebbt.beats, ebbt.ticks); + break; + + case AudioClock::SMPTE: + session->smpte_duration (end - start, smpte); + snprintf (buf, sizeof (buf), "%02" PRId32 ":%02" PRId32 ":%02" PRId32 ":%02" PRId32, smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + break; + + case AudioClock::MinSec: + /* XXX fix this to compute min/sec properly */ + session->smpte_duration (end - start, smpte); + secs = smpte.seconds + ((float) smpte.frames / session->smpte_frames_per_second); + snprintf (buf, sizeof (buf), "%02ld:%02ld:%.4f", smpte.hours, smpte.minutes, secs); + break; + + default: + snprintf (buf, sizeof(buf), "%u", end - start); + break; + } + + if (xpos >= 0 && ypos >=0) { + set_verbose_canvas_cursor (buf, xpos + offset, ypos + offset); + } + else { + set_verbose_canvas_cursor (buf, drag_info.current_pointer_x + offset, drag_info.current_pointer_y + offset); + } + show_verbose_canvas_cursor (); +} + +void +Editor::collect_new_region_view (AudioRegionView* rv) +{ + latest_regionview = rv; +} + +void +Editor::start_selection_grab (GtkCanvasItem* item, GdkEvent* event) +{ + if (clicked_regionview == 0) { + return; + } + + /* lets try to create new Region for the selection */ + + vector new_regions; + create_region_from_selection (new_regions); + + if (new_regions.empty()) { + return; + } + + /* XXX fix me one day to use all new regions */ + + Region* region = new_regions.front(); + + /* add it to the current stream/playlist. + + tricky: the streamview for the track will add a new regionview. we will + catch the signal it sends when it creates the regionview to + set the regionview we want to then drag. + */ + + latest_regionview = 0; + SigC::Connection c = clicked_audio_trackview->view->AudioRegionViewAdded.connect (slot (*this, &Editor::collect_new_region_view)); + + /* A selection grab currently creates two undo/redo operations, one for + creating the new region and another for moving it. + */ + + begin_reversible_command (_("selection grab")); + + Playlist* playlist = clicked_trackview->playlist(); + + session->add_undo (playlist->get_memento ()); + clicked_trackview->playlist()->add_region (*region, selection->time[clicked_selection].start); + session->add_redo_no_execute (playlist->get_memento ()); + + commit_reversible_command (); + + c.disconnect (); + + if (latest_regionview == 0) { + /* something went wrong */ + return; + } + + /* we need to deselect all other regionviews, and select this one + i'm ignoring undo stuff, because the region creation will take care of it */ + selection->set (latest_regionview); + + drag_info.item = latest_regionview->get_canvas_group(); + drag_info.data = latest_regionview; + drag_info.motion_callback = &Editor::region_drag_motion_callback; + drag_info.finished_callback = &Editor::region_drag_finished_callback; + + start_grab (event); + + drag_info.last_trackview = clicked_trackview; + drag_info.last_frame_position = latest_regionview->region.position(); + drag_info.pointer_frame_offset = drag_info.grab_frame - drag_info.last_frame_position; + + show_verbose_time_cursor (drag_info.last_frame_position, 10); +} + +void +Editor::cancel_selection () +{ + for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) { + (*i)->hide_selection (); + } + selection->clear (); + clicked_selection = 0; +} + +void +Editor::start_selection_op (GtkCanvasItem* item, GdkEvent* event, SelectionOp op) +{ + jack_nframes_t start = 0; + jack_nframes_t end = 0; + + if (session == 0) { + return; + } + + drag_info.item = item; + drag_info.motion_callback = &Editor::drag_selection; + drag_info.finished_callback = &Editor::end_selection_op; + + selection_op = op; + + switch (op) { + case CreateSelection: + + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) { + drag_info.copy = true; + } else { + drag_info.copy = false; + } + start_grab (event, selector_cursor); + break; + + case SelectionStartTrim: + clicked_trackview->order_selection_trims (item, true); + start_grab (event, trimmer_cursor); + start = selection->time[clicked_selection].start; + drag_info.pointer_frame_offset = drag_info.grab_frame - start; + break; + + case SelectionEndTrim: + clicked_trackview->order_selection_trims (item, false); + start_grab (event, trimmer_cursor); + end = selection->time[clicked_selection].end; + drag_info.pointer_frame_offset = drag_info.grab_frame - end; + break; + + case SelectionMove: + start = selection->time[clicked_selection].start; + start_grab (event); + drag_info.pointer_frame_offset = drag_info.grab_frame - start; + break; + } + + if (selection_op == SelectionMove) { + show_verbose_time_cursor(start, 10); + } else { + show_verbose_time_cursor(drag_info.current_pointer_frame, 10); + } +} + +void +Editor::drag_selection (GtkCanvasItem* item, GdkEvent* event) +{ + jack_nframes_t start = 0; + jack_nframes_t end = 0; + jack_nframes_t length; + jack_nframes_t pending_position; + + if ((int32_t) drag_info.current_pointer_frame > drag_info.pointer_frame_offset) { + pending_position = drag_info.current_pointer_frame - drag_info.pointer_frame_offset; + } + else { + pending_position = 0; + } + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (pending_position); + } + + /* only alter selection if the current frame is + different from the last frame position (adjusted) + */ + + if (pending_position == drag_info.last_pointer_frame) return; + + switch (selection_op) { + case CreateSelection: + + if (drag_info.first_move) { + snap_to (drag_info.grab_frame); + } + + if (pending_position < drag_info.grab_frame) { + start = pending_position; + end = drag_info.grab_frame; + } else { + end = pending_position; + start = drag_info.grab_frame; + } + + /* first drag: Either add to the selection + or create a new selection-> + */ + + if (drag_info.first_move) { + + begin_reversible_command (_("range selection")); + + if (drag_info.copy) { + /* adding to the selection */ + clicked_selection = selection->add (start, end); + drag_info.copy = false; + } else { + /* new selection-> */ + clicked_selection = selection->set (clicked_trackview, start, end); + } + } + break; + + case SelectionStartTrim: + + if (drag_info.first_move) { + begin_reversible_command (_("trim selection start")); + } + + start = selection->time[clicked_selection].start; + end = selection->time[clicked_selection].end; + + if (pending_position > end) { + start = end; + } else { + start = pending_position; + } + break; + + case SelectionEndTrim: + + if (drag_info.first_move) { + begin_reversible_command (_("trim selection end")); + } + + start = selection->time[clicked_selection].start; + end = selection->time[clicked_selection].end; + + if (pending_position < start) { + end = start; + } else { + end = pending_position; + } + + break; + + case SelectionMove: + + if (drag_info.first_move) { + begin_reversible_command (_("move selection")); + } + + start = selection->time[clicked_selection].start; + end = selection->time[clicked_selection].end; + + length = end - start; + + start = pending_position; + snap_to (start); + + end = start + length; + + break; + } + + + if (event->button.x >= track_canvas_scroller.get_hadjustment()->get_value() + canvas_width) { + start_canvas_autoscroll (1); + } + + if (start != end) { + selection->replace (clicked_selection, start, end); + } + + drag_info.last_pointer_frame = pending_position; + drag_info.first_move = false; + + if (selection_op == SelectionMove) { + show_verbose_time_cursor(start, 10); + } else { + show_verbose_time_cursor(pending_position, 10); + } +} + +void +Editor::end_selection_op (GtkCanvasItem* item, GdkEvent* event) +{ + if (!drag_info.first_move) { + drag_selection (item, event); + /* XXX this is not object-oriented programming at all. ick */ + if (selection->time.consolidate()) { + selection->TimeChanged (); + } + commit_reversible_command (); + } else { + /* just a click, no pointer movement.*/ + + if (Keyboard::no_modifier_keys_pressed (&event->button)) { + + selection->clear_time(); + + } + } + + /* XXX what happens if its a music selection? */ + session->set_audio_range (selection->time); + stop_canvas_autoscroll (); +} + +void +Editor::start_trim (GtkCanvasItem* item, GdkEvent* event) +{ + double speed = 1.0; + TimeAxisView* tvp = clicked_trackview; + AudioTimeAxisView* tv = dynamic_cast(tvp); + + if (tv && tv->is_audio_track()) { + speed = tv->get_diskstream()->speed(); + } + + jack_nframes_t region_start = (jack_nframes_t) (clicked_regionview->region.position() / speed); + jack_nframes_t region_end = (jack_nframes_t) (clicked_regionview->region.last_frame() / speed); + jack_nframes_t region_length = (jack_nframes_t) (clicked_regionview->region.length() / speed); + + //drag_info.item = clicked_regionview->get_name_highlight(); + drag_info.item = item; + drag_info.motion_callback = &Editor::trim_motion_callback; + drag_info.finished_callback = &Editor::trim_finished_callback; + + start_grab (event, trimmer_cursor); + + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) { + trim_op = ContentsTrim; + } else { + /* These will get overridden for a point trim.*/ + if (drag_info.current_pointer_frame < (region_start + region_length/2)) { + /* closer to start */ + trim_op = StartTrim; + } else if (drag_info.current_pointer_frame > (region_end - region_length/2)) { + /* closer to end */ + trim_op = EndTrim; + } + } + + switch (trim_op) { + case StartTrim: + show_verbose_time_cursor(region_start, 10); + break; + case EndTrim: + show_verbose_time_cursor(region_end, 10); + break; + case ContentsTrim: + show_verbose_time_cursor(drag_info.current_pointer_frame, 10); + break; + } + + flush_track_canvas (); +} + +void +Editor::trim_motion_callback (GtkCanvasItem* item, GdkEvent* event) +{ + AudioRegionView* rv = clicked_regionview; + jack_nframes_t frame_delta = 0; + bool left_direction; + bool obey_snap = !Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier()); + + /* snap modifier works differently here.. + its' current state has to be passed to the + various trim functions in order to work properly + */ + + double speed = 1.0; + TimeAxisView* tvp = clicked_trackview; + AudioTimeAxisView* tv = dynamic_cast(tvp); + + if (tv && tv->is_audio_track()) { + speed = tv->get_diskstream()->speed(); + } + + if (drag_info.last_pointer_frame > drag_info.current_pointer_frame) { + left_direction = true; + } else { + left_direction = false; + } + + if (obey_snap) { + snap_to (drag_info.current_pointer_frame); + } + + if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) { + return; + } + + if (drag_info.first_move) { + + string trim_type; + + switch (trim_op) { + case StartTrim: + trim_type = "Region start trim"; + break; + case EndTrim: + trim_type = "Region end trim"; + break; + case ContentsTrim: + trim_type = "Region content trim"; + break; + } + + begin_reversible_command (trim_type); + + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + (*i)->region.freeze (); + (*i)->temporarily_hide_envelope (); + session->add_undo ((*i)->region.playlist()->get_memento()); + } + } + + if (left_direction) { + frame_delta = (drag_info.last_pointer_frame - drag_info.current_pointer_frame); + } else { + frame_delta = (drag_info.current_pointer_frame - drag_info.last_pointer_frame); + } + + switch (trim_op) { + case StartTrim: + if ((left_direction == false) && (drag_info.current_pointer_frame <= rv->region.first_frame()/speed)) { + break; + } else { + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + single_start_trim (**i, frame_delta, left_direction, obey_snap); + } + break; + } + + case EndTrim: + if ((left_direction == true) && (drag_info.current_pointer_frame > (jack_nframes_t) (rv->region.last_frame()/speed))) { + break; + } else { + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) { + single_end_trim (**i, frame_delta, left_direction, obey_snap); + } + break; + } + + case ContentsTrim: + { + bool swap_direction = false; + + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Control)) { + swap_direction = true; + } + + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); + i != selection->audio_regions.by_layer().end(); ++i) + { + single_contents_trim (**i, frame_delta, left_direction, swap_direction, obey_snap); + } + } + break; + } + + switch (trim_op) { + case StartTrim: + show_verbose_time_cursor((jack_nframes_t) (rv->region.position()/speed), 10); + break; + case EndTrim: + show_verbose_time_cursor((jack_nframes_t) (rv->region.last_frame()/speed), 10); + break; + case ContentsTrim: + show_verbose_time_cursor(drag_info.current_pointer_frame, 10); + break; + } + + drag_info.last_pointer_frame = drag_info.current_pointer_frame; + drag_info.first_move = false; +} + +void +Editor::single_contents_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool swap_direction, bool obey_snap) +{ + Region& region (rv.region); + + if (region.locked()) { + return; + } + + jack_nframes_t new_bound; + + double speed = 1.0; + TimeAxisView* tvp = clicked_trackview; + AudioTimeAxisView* tv = dynamic_cast(tvp); + + if (tv && tv->is_audio_track()) { + speed = tv->get_diskstream()->speed(); + } + + if (left_direction) { + if (swap_direction) { + new_bound = (jack_nframes_t) (region.position()/speed) + frame_delta; + } else { + new_bound = (jack_nframes_t) (region.position()/speed) - frame_delta; + } + } else { + if (swap_direction) { + new_bound = (jack_nframes_t) (region.position()/speed) - frame_delta; + } else { + new_bound = (jack_nframes_t) (region.position()/speed) + frame_delta; + } + } + + if (obey_snap) { + snap_to (new_bound); + } + region.trim_start ((jack_nframes_t) (new_bound * speed), this); + rv.region_changed (StartChanged); +} + +void +Editor::single_start_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap) +{ + Region& region (rv.region); + + if (region.locked()) { + return; + } + + jack_nframes_t new_bound; + + double speed = 1.0; + TimeAxisView* tvp = clicked_trackview; + AudioTimeAxisView* tv = dynamic_cast(tvp); + + if (tv && tv->is_audio_track()) { + speed = tv->get_diskstream()->speed(); + } + + if (left_direction) { + new_bound = (jack_nframes_t) (region.position()/speed) - frame_delta; + } else { + new_bound = (jack_nframes_t) (region.position()/speed) + frame_delta; + } + + if (obey_snap) { + snap_to (new_bound, (left_direction ? 0 : 1)); + } + + region.trim_front ((jack_nframes_t) (new_bound * speed), this); + + rv.region_changed (Change (LengthChanged|PositionChanged|StartChanged)); +} + +void +Editor::single_end_trim (AudioRegionView& rv, jack_nframes_t frame_delta, bool left_direction, bool obey_snap) +{ + Region& region (rv.region); + + if (region.locked()) { + return; + } + + jack_nframes_t new_bound; + + double speed = 1.0; + TimeAxisView* tvp = clicked_trackview; + AudioTimeAxisView* tv = dynamic_cast(tvp); + + if (tv && tv->is_audio_track()) { + speed = tv->get_diskstream()->speed(); + } + + if (left_direction) { + new_bound = (jack_nframes_t) ((region.last_frame() + 1)/speed) - frame_delta; + } else { + new_bound = (jack_nframes_t) ((region.last_frame() + 1)/speed) + frame_delta; + } + + if (obey_snap) { + snap_to (new_bound); + } + region.trim_end ((jack_nframes_t) (new_bound * speed), this); + rv.region_changed (LengthChanged); +} + +void +Editor::trim_finished_callback (GtkCanvasItem* item, GdkEvent* event) +{ + if (!drag_info.first_move) { + trim_motion_callback (item, event); + + if (!clicked_regionview->get_selected()) { + thaw_region_after_trim (*clicked_regionview); + } else { + + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); + i != selection->audio_regions.by_layer().end(); ++i) + { + thaw_region_after_trim (**i); + } + } + commit_reversible_command(); + } else { + /* no mouse movement */ + point_trim (event); + } + + flush_track_canvas (); +} + +void +Editor::point_trim (GdkEvent* event) +{ + AudioRegionView* rv = clicked_regionview; + jack_nframes_t new_bound = drag_info.current_pointer_frame; + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (new_bound); + } + + /* Choose action dependant on which button was pressed */ + switch (event->button.button) { + case 1: + trim_op = StartTrim; + begin_reversible_command (_("Start point trim")); + + if (rv->get_selected()) { + + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); + i != selection->audio_regions.by_layer().end(); ++i) + { + if (!(*i)->region.locked()) { + session->add_undo ((*i)->region.playlist()->get_memento()); + (*i)->region.trim_front (new_bound, this); + session->add_redo_no_execute ((*i)->region.playlist()->get_memento()); + } + } + + } else { + + if (!rv->region.locked()) { + session->add_undo (rv->region.playlist()->get_memento()); + rv->region.trim_front (new_bound, this); + session->add_redo_no_execute (rv->region.playlist()->get_memento()); + } + } + + commit_reversible_command(); + + break; + case 2: + trim_op = EndTrim; + begin_reversible_command (_("End point trim")); + + if (rv->get_selected()) { + + for (list::const_iterator i = selection->audio_regions.by_layer().begin(); i != selection->audio_regions.by_layer().end(); ++i) + { + if (!(*i)->region.locked()) { + session->add_undo ((*i)->region.playlist()->get_memento()); + (*i)->region.trim_end (new_bound, this); + session->add_redo_no_execute ((*i)->region.playlist()->get_memento()); + } + } + + } else { + + if (!rv->region.locked()) { + session->add_undo (rv->region.playlist()->get_memento()); + rv->region.trim_end (new_bound, this); + session->add_redo_no_execute (rv->region.playlist()->get_memento()); + } + } + + commit_reversible_command(); + + break; + default: + break; + } +} + +void +Editor::thaw_region_after_trim (AudioRegionView& rv) +{ + Region& region (rv.region); + + if (region.locked()) { + return; + } + + region.thaw (_("trimmed region")); + session->add_redo_no_execute (region.playlist()->get_memento()); + + rv.unhide_envelope (); +} + +void +Editor::hide_marker (GtkCanvasItem* item, GdkEvent* event) +{ + Marker* marker; + bool is_start; + + if ((marker = static_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + fatal << _("programming error: marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + Location* location = find_location_from_marker (marker, is_start); + location->set_hidden (true, this); +} + + +void +Editor::start_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event, RangeMarkerOp op) +{ + + if (session == 0) { + return; + } + + drag_info.item = item; + drag_info.motion_callback = &Editor::drag_range_markerbar_op; + drag_info.finished_callback = &Editor::end_range_markerbar_op; + + range_marker_op = op; + + if (!temp_location) { + temp_location = new Location; + } + + switch (op) { + case CreateRangeMarker: + case CreateTransportMarker: + + if (Keyboard::modifier_state_equals (event->button.state, Keyboard::Shift)) { + drag_info.copy = true; + } else { + drag_info.copy = false; + } + start_grab (event, selector_cursor); + break; + } + + show_verbose_time_cursor(drag_info.current_pointer_frame, 10); + +} + +void +Editor::drag_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event) +{ + jack_nframes_t start = 0; + jack_nframes_t end = 0; + + GtkCanvasItem * crect = (range_marker_op == CreateRangeMarker) ? range_bar_drag_rect: transport_bar_drag_rect; + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (drag_info.current_pointer_frame); + } + + /* only alter selection if the current frame is + different from the last frame position. + */ + + if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) return; + + switch (range_marker_op) { + case CreateRangeMarker: + case CreateTransportMarker: + if (drag_info.first_move) { + snap_to (drag_info.grab_frame); + } + + if (drag_info.current_pointer_frame < drag_info.grab_frame) { + start = drag_info.current_pointer_frame; + end = drag_info.grab_frame; + } else { + end = drag_info.current_pointer_frame; + start = drag_info.grab_frame; + } + + /* first drag: Either add to the selection + or create a new selection-> + */ + + if (drag_info.first_move) { + + temp_location->set (start, end); + + gtk_canvas_item_show (crect); + + update_marker_drag_item (temp_location); + gtk_canvas_item_show (range_marker_drag_rect); + gtk_canvas_item_raise_to_top (range_marker_drag_rect); + + } + break; + } + + + if (event->button.x >= track_canvas_scroller.get_hadjustment()->get_value() + canvas_width) { + start_canvas_autoscroll (1); + } + + if (start != end) { + temp_location->set (start, end); + + double x1 = frame_to_pixel (start); + double x2 = frame_to_pixel (end); + gtk_canvas_item_set (crect, "x1", x1, "x2", x2, NULL); + + update_marker_drag_item (temp_location); + } + + drag_info.last_pointer_frame = drag_info.current_pointer_frame; + drag_info.first_move = false; + + show_verbose_time_cursor(drag_info.current_pointer_frame, 10); + +} + +void +Editor::end_range_markerbar_op (GtkCanvasItem* item, GdkEvent* event) +{ + Location * newloc = 0; + + if (!drag_info.first_move) { + drag_range_markerbar_op (item, event); + + switch (range_marker_op) + { + case CreateRangeMarker: + begin_reversible_command (_("new range marker")); + session->add_undo (session->locations()->get_memento()); + newloc = new Location(temp_location->start(), temp_location->end(), "unnamed"); + session->locations()->add (newloc, true); + session->add_redo_no_execute (session->locations()->get_memento()); + commit_reversible_command (); + + gtk_canvas_item_hide (range_bar_drag_rect); + gtk_canvas_item_hide (range_marker_drag_rect); + break; + + case CreateTransportMarker: + // popup menu to pick loop or punch + new_transport_marker_context_menu (&event->button, item); + + break; + } + } else { + /* just a click, no pointer movement.*/ + + if (Keyboard::no_modifier_keys_pressed (&event->button)) { + + // nothing yet + + } + } + + stop_canvas_autoscroll (); +} + + + +void +Editor::start_mouse_zoom (GtkCanvasItem* item, GdkEvent* event) +{ + drag_info.item = item; + drag_info.motion_callback = &Editor::drag_mouse_zoom; + drag_info.finished_callback = &Editor::end_mouse_zoom; + + start_grab (event, zoom_cursor); + + show_verbose_time_cursor (drag_info.current_pointer_frame, 10); +} + +void +Editor::drag_mouse_zoom (GtkCanvasItem* item, GdkEvent* event) +{ + jack_nframes_t start; + jack_nframes_t end; + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (drag_info.current_pointer_frame); + + if (drag_info.first_move) { + snap_to (drag_info.grab_frame); + } + } + + if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) return; + + /* base start and end on initial click position */ + if (drag_info.current_pointer_frame < drag_info.grab_frame) { + start = drag_info.current_pointer_frame; + end = drag_info.grab_frame; + } else { + end = drag_info.current_pointer_frame; + start = drag_info.grab_frame; + } + + if (start != end) { + + if (drag_info.first_move) { + gtk_canvas_item_show (zoom_rect); + gtk_canvas_item_raise_to_top (zoom_rect); + } + + reposition_zoom_rect(start, end); + + drag_info.last_pointer_frame = drag_info.current_pointer_frame; + drag_info.first_move = false; + + show_verbose_time_cursor (drag_info.current_pointer_frame, 10); + } +} + +void +Editor::end_mouse_zoom (GtkCanvasItem* item, GdkEvent* event) +{ + if (!drag_info.first_move) { + drag_mouse_zoom (item, event); + + if (drag_info.grab_frame < drag_info.last_pointer_frame) { + temporal_zoom_by_frame (drag_info.grab_frame, drag_info.last_pointer_frame, "mouse zoom"); + } else { + temporal_zoom_by_frame (drag_info.last_pointer_frame, drag_info.grab_frame, "mouse zoom"); + } + } else { + temporal_zoom_to_frame (false, drag_info.grab_frame); + /* + temporal_zoom_step (false); + center_screen (drag_info.grab_frame); + */ + } + + gtk_canvas_item_hide (zoom_rect); +} + +void +Editor::reposition_zoom_rect (jack_nframes_t start, jack_nframes_t end) +{ + double x1 = frame_to_pixel (start); + double x2 = frame_to_pixel (end); + double y2 = canvas_height - 2; + + gtk_object_set (GTK_OBJECT(zoom_rect), + "x1", x1, + "y1", 1.0, + "x2", x2, + "y2", y2, + NULL); +} + +void +Editor::start_rubberband_select (GtkCanvasItem* item, GdkEvent* event) +{ + drag_info.item = item; + drag_info.motion_callback = &Editor::drag_rubberband_select; + drag_info.finished_callback = &Editor::end_rubberband_select; + + start_grab (event, cross_hair_cursor); + + show_verbose_time_cursor (drag_info.current_pointer_frame, 10); +} + +void +Editor::drag_rubberband_select (GtkCanvasItem* item, GdkEvent* event) +{ + jack_nframes_t start; + jack_nframes_t end; + double y1; + double y2; + + /* use a bigger drag threshold than the default */ + + if (abs ((int) (drag_info.current_pointer_frame - drag_info.grab_frame)) < 8) { + return; + } + +// if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { +// snap_to (drag_info.current_pointer_frame); + +// if (drag_info.first_move) { +// snap_to (drag_info.grab_frame); +// } +// } + + + /* base start and end on initial click position */ + if (drag_info.current_pointer_frame < drag_info.grab_frame) { + start = drag_info.current_pointer_frame; + end = drag_info.grab_frame; + } else { + end = drag_info.current_pointer_frame; + start = drag_info.grab_frame; + } + + if (drag_info.current_pointer_y < drag_info.grab_y) { + y1 = drag_info.current_pointer_y; + y2 = drag_info.grab_y; + } + else { + y2 = drag_info.current_pointer_y; + y1 = drag_info.grab_y; + } + + + if (start != end || y1 != y2) { + + double x1 = frame_to_pixel (start); + double x2 = frame_to_pixel (end); + + gtk_object_set (GTK_OBJECT(rubberband_rect), + "x1", x1, + "y1", y1, + "x2", x2, + "y2", y2, + NULL); + + gtk_canvas_item_show (rubberband_rect); + gtk_canvas_item_raise_to_top (rubberband_rect); + + drag_info.last_pointer_frame = drag_info.current_pointer_frame; + drag_info.first_move = false; + + show_verbose_time_cursor (drag_info.current_pointer_frame, 10); + } +} + +void +Editor::end_rubberband_select (GtkCanvasItem* item, GdkEvent* event) +{ + if (!drag_info.first_move) { + + drag_rubberband_select (item, event); + + double y1,y2; + if (drag_info.current_pointer_y < drag_info.grab_y) { + y1 = drag_info.current_pointer_y; + y2 = drag_info.grab_y; + } + else { + y2 = drag_info.current_pointer_y; + y1 = drag_info.grab_y; + } + + + bool add = Keyboard::modifier_state_contains (event->button.state, Keyboard::Shift); + bool commit; + + begin_reversible_command (_("select regions")); + + if (drag_info.grab_frame < drag_info.last_pointer_frame) { + commit = select_all_within (drag_info.grab_frame, drag_info.last_pointer_frame, y1, y2, add); + } else { + commit = select_all_within (drag_info.last_pointer_frame, drag_info.grab_frame, y1, y2, add); + } + + if (commit) { + commit_reversible_command (); + } + + } else { + selection->clear_audio_regions(); + selection->clear_points (); + selection->clear_lines (); + } + + gtk_canvas_item_hide (rubberband_rect); +} + + +gint +Editor::mouse_rename_region (GtkCanvasItem* item, GdkEvent* event) +{ + using namespace Gtkmmext; + + ArdourPrompter prompter (false); + + prompter.set_prompt (_("Name for region:")); + prompter.set_initial_text (clicked_regionview->region.name()); + prompter.show_all (); + prompter.done.connect (Main::quit.slot()); + + Main::run (); + + if (prompter.status == Prompter::cancelled) { + return TRUE; + } + + string str; + + prompter.get_result(str); + clicked_regionview->region.set_name (str); + + return TRUE; +} + +void +Editor::start_time_fx (GtkCanvasItem* item, GdkEvent* event) +{ + drag_info.item = item; + drag_info.motion_callback = &Editor::time_fx_motion; + drag_info.finished_callback = &Editor::end_time_fx; + + start_grab (event); + + show_verbose_time_cursor (drag_info.current_pointer_frame, 10); +} + +void +Editor::time_fx_motion (GtkCanvasItem *item, GdkEvent* event) +{ + AudioRegionView* rv = clicked_regionview; + + if (!Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) { + snap_to (drag_info.current_pointer_frame); + } + + if (drag_info.current_pointer_frame == drag_info.last_pointer_frame) { + return; + } + + if (drag_info.current_pointer_frame > rv->region.position()) { + rv->get_time_axis_view().show_timestretch (rv->region.position(), drag_info.current_pointer_frame); + } + + drag_info.last_pointer_frame = drag_info.current_pointer_frame; + drag_info.first_move = false; + + show_verbose_time_cursor (drag_info.current_pointer_frame, 10); +} + +void +Editor::end_time_fx (GtkCanvasItem* item, GdkEvent* event) +{ + clicked_regionview->get_time_axis_view().hide_timestretch (); + + if (drag_info.first_move) { + return; + } + + jack_nframes_t newlen = drag_info.last_pointer_frame - clicked_regionview->region.position(); + float percentage = (float) ((double) newlen - (double) clicked_regionview->region.length()) / ((double) newlen) * 100.0f; + + begin_reversible_command (_("timestretch")); + + if (run_timestretch (selection->audio_regions, percentage) == 0) { + session->commit_reversible_command (); + } +} + +void +Editor::mouse_brush_insert_region (AudioRegionView* rv, jack_nframes_t pos) +{ + /* no brushing without a useful snap setting */ + + switch (snap_mode) { + case SnapMagnetic: + return; /* can't work because it allows region to be placed anywhere */ + default: + break; /* OK */ + } + + switch (snap_type) { + case SnapToFrame: + case SnapToMark: + case SnapToEditCursor: + return; + + default: + break; + } + + /* don't brush a copy over the original */ + + if (pos == rv->region.position()) { + return; + } + + AudioTimeAxisView* atv = dynamic_cast(&rv->get_time_axis_view()); + + if (atv == 0 || !atv->is_audio_track()) { + return; + } + + Playlist* playlist = atv->playlist(); + double speed = atv->get_diskstream()->speed(); + + session->add_undo (playlist->get_memento()); + playlist->add_region (*(new AudioRegion (rv->region)), (jack_nframes_t) (pos * speed)); + session->add_redo_no_execute (playlist->get_memento()); + + // playlist is frozen, so we have to update manually + + playlist->StateChanged (Change (~0)); /* EMIT SIGNAL */ +} + +gint +Editor::track_height_step_timeout () +{ + struct timeval now; + struct timeval delta; + + gettimeofday (&now, 0); + timersub (&now, &last_track_height_step_timestamp, &delta); + + if (delta.tv_sec * 1000000 + delta.tv_usec > 250000) { /* milliseconds */ + current_stepping_trackview = 0; + return FALSE; + } + return TRUE; +} diff --git a/gtk2_ardour/editor_nudge.cc b/gtk2_ardour/editor_nudge.cc new file mode 100644 index 0000000000..f7203d93b8 --- /dev/null +++ b/gtk2_ardour/editor_nudge.cc @@ -0,0 +1,30 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include "editor.h" + +#include "i18n.h" + +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc new file mode 100644 index 0000000000..756e2ea8ba --- /dev/null +++ b/gtk2_ardour/editor_ops.cc @@ -0,0 +1,3627 @@ +/* + Copyright (C) 2000-2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ardour_ui.h" +#include "editor.h" +#include "time_axis_view.h" +#include "audio_time_axis.h" +#include "automation_time_axis.h" +#include "streamview.h" +#include "regionview.h" +#include "rgb_macros.h" +#include "extra_bind.h" +#include "selection_templates.h" +#include "selection.h" +#include "library_ui.h" +#include "editing.h" +#include "gtk-custom-hruler.h" + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; +using namespace SigC; +using namespace Gtk; +using namespace Editing; + +/*********************************************************************** + Editor operations + ***********************************************************************/ + +void +Editor::undo (uint32_t n) +{ + if (session) { + session->undo (n); + } +} + +void +Editor::redo (uint32_t n) +{ + if (session) { + session->redo (n); + } +} + +int +Editor::ensure_cursor (jack_nframes_t *pos) +{ + *pos = edit_cursor->current_frame; + return 0; +} + +void +Editor::split_region () +{ + split_region_at (edit_cursor->current_frame); +} + +void +Editor::split_region_at (jack_nframes_t where) +{ + split_regions_at (where, selection->audio_regions); +} + +void +Editor::split_regions_at (jack_nframes_t where, AudioRegionSelection& regions) +{ + begin_reversible_command (_("split")); + + snap_to (where); + for (AudioRegionSelection::iterator a = regions.begin(); a != regions.end(); ) { + + AudioRegionSelection::iterator tmp; + + tmp = a; + ++tmp; + + Playlist* pl = (*a)->region.playlist(); + + _new_regionviews_show_envelope = (*a)->envelope_visible(); + + if (pl) { + session->add_undo (pl->get_memento()); + pl->split_region ((*a)->region, where); + session->add_redo_no_execute (pl->get_memento()); + } + + a = tmp; + } + + commit_reversible_command (); + _new_regionviews_show_envelope = false; +} + +void +Editor::remove_clicked_region () +{ + if (clicked_audio_trackview == 0 || clicked_regionview == 0) { + return; + } + + Playlist* playlist = clicked_audio_trackview->playlist(); + + begin_reversible_command (_("remove region")); + session->add_undo (playlist->get_memento()); + playlist->remove_region (&clicked_regionview->region); + session->add_redo_no_execute (playlist->get_memento()); + commit_reversible_command (); +} + +void +Editor::destroy_clicked_region () +{ + int32_t selected = selection->audio_regions.size(); + + if (!session || clicked_regionview == 0 && selected == 0) { + return; + } + + vector choices; + string prompt; + + prompt = compose (_(" This is destructive, will possibly delete audio files\n\ +It cannot be undone\n\ +Do you really want to destroy %1 ?"), + (selected > 1 ? + _("these regions") : _("this region"))); + + if (selected > 1) { + choices.push_back (_("Yes, destroy them.")); + } else { + choices.push_back (_("Yes, destroy it.")); + } + + choices.push_back (_("No, do nothing.")); + + Gtkmmext::Choice prompter (prompt, choices); + + prompter.chosen.connect (Gtk::Main::quit.slot()); + prompter.show_all (); + + Gtk::Main::run (); + + if (prompter.get_choice() != 0) { + return; + } + + if (selected > 0) { + list r; + + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + r.push_back (&(*i)->region); + } + + session->destroy_regions (r); + + } else if (clicked_regionview) { + session->destroy_region (&clicked_regionview->region); + } +} + +AudioRegion * +Editor::select_region_for_operation (int dir, TimeAxisView **tv) +{ + AudioRegionView* rv; + AudioRegion *region; + jack_nframes_t start = 0; + + if (selection->time.start () == selection->time.end_frame ()) { + + /* no current selection-> is there a selected regionview? */ + + if (selection->audio_regions.empty()) { + return 0; + } + + } + + region = 0; + + if (!selection->audio_regions.empty()) { + + rv = *(selection->audio_regions.begin()); + (*tv) = &rv->get_time_axis_view(); + region = &rv->region; + + } else if (!selection->tracks.empty()) { + + (*tv) = selection->tracks.front(); + + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast (*tv)) != 0) { + Playlist *pl; + + if ((pl = atv->playlist()) == 0) { + return 0; + } + + region = dynamic_cast (pl->top_region_at (start)); + } + } + + return region; +} + +void +Editor::extend_selection_to_end_of_region (bool next) +{ + TimeAxisView *tv; + Region *region; + jack_nframes_t start; + + if ((region = select_region_for_operation (next ? 1 : 0, &tv)) == 0) { + return; + } + + if (region && selection->time.start () == selection->time.end_frame ()) { + start = region->position(); + } else { + start = selection->time.start (); + } + + /* Try to leave the selection with the same route if possible */ + + if ((tv = selection->time.track) == 0) { + return; + } + + begin_reversible_command (_("extend selection")); + selection->set (tv, start, region->position() + region->length()); + commit_reversible_command (); +} + +void +Editor::extend_selection_to_start_of_region (bool previous) +{ + TimeAxisView *tv; + Region *region; + jack_nframes_t end; + + if ((region = select_region_for_operation (previous ? -1 : 0, &tv)) == 0) { + return; + } + + if (region && selection->time.start () == selection->time.end_frame ()) { + end = region->position() + region->length(); + } else { + end = selection->time.end_frame (); + } + + /* Try to leave the selection with the same route if possible */ + + if ((tv = selection->time.track) == 0) { + return; + } + + begin_reversible_command (_("extend selection")); + selection->set (tv, region->position(), end); + commit_reversible_command (); +} + + +void +Editor::nudge_forward (bool next) +{ + jack_nframes_t distance; + jack_nframes_t next_distance; + + if (!session) return; + + if (!selection->audio_regions.empty()) { + + begin_reversible_command (_("nudge forward")); + + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + AudioRegion& r ((*i)->region); + + distance = get_nudge_distance (r.position(), next_distance); + + if (next) { + distance = next_distance; + } + + session->add_undo (r.playlist()->get_memento()); + r.set_position (r.position() + distance, this); + session->add_redo_no_execute (r.playlist()->get_memento()); + } + + commit_reversible_command (); + + } else { + distance = get_nudge_distance (playhead_cursor->current_frame, next_distance); + session->request_locate (playhead_cursor->current_frame + distance); + } +} + +void +Editor::nudge_backward (bool next) +{ + jack_nframes_t distance; + jack_nframes_t next_distance; + + if (!session) return; + + if (!selection->audio_regions.empty()) { + + begin_reversible_command (_("nudge forward")); + + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + AudioRegion& r ((*i)->region); + + distance = get_nudge_distance (r.position(), next_distance); + + if (next) { + distance = next_distance; + } + + session->add_undo (r.playlist()->get_memento()); + + if (r.position() > distance) { + r.set_position (r.position() - distance, this); + } else { + r.set_position (0, this); + } + session->add_redo_no_execute (r.playlist()->get_memento()); + } + + commit_reversible_command (); + + } else { + + distance = get_nudge_distance (playhead_cursor->current_frame, next_distance); + + if (playhead_cursor->current_frame > distance) { + session->request_locate (playhead_cursor->current_frame - distance); + } else { + session->request_locate (0); + } + } +} + +void +Editor::nudge_forward_capture_offset () +{ + jack_nframes_t distance; + + if (!session) return; + + if (!selection->audio_regions.empty()) { + + begin_reversible_command (_("nudge forward")); + + distance = session->worst_output_latency(); + + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + AudioRegion& r ((*i)->region); + + session->add_undo (r.playlist()->get_memento()); + r.set_position (r.position() + distance, this); + session->add_redo_no_execute (r.playlist()->get_memento()); + } + + commit_reversible_command (); + + } +} + +void +Editor::nudge_backward_capture_offset () +{ + jack_nframes_t distance; + + if (!session) return; + + if (!selection->audio_regions.empty()) { + + begin_reversible_command (_("nudge forward")); + + distance = session->worst_output_latency(); + + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + AudioRegion& r ((*i)->region); + + session->add_undo (r.playlist()->get_memento()); + + if (r.position() > distance) { + r.set_position (r.position() - distance, this); + } else { + r.set_position (0, this); + } + session->add_redo_no_execute (r.playlist()->get_memento()); + } + + commit_reversible_command (); + } +} + +/* DISPLAY MOTION */ + +void +Editor::move_to_start () +{ + session->request_locate (0); +} + +void +Editor::move_to_end () +{ + + session->request_locate (session->current_end_frame()); +} + +void +Editor::build_region_boundary_cache () +{ + jack_nframes_t pos = 0; + RegionPoint point; + Region *r; + TrackViewList tracks; + + region_boundary_cache.clear (); + + if (session == 0) { + return; + } + + switch (snap_type) { + case SnapToRegionStart: + point = Start; + break; + case SnapToRegionEnd: + point = End; + break; + case SnapToRegionSync: + point = SyncPoint; + break; + case SnapToRegionBoundary: + point = Start; + break; + default: + fatal << compose (_("build_region_boundary_cache called with snap_type = %1"), snap_type) << endmsg; + /*NOTREACHED*/ + return; + } + + TimeAxisView *ontrack = 0; + + while (pos < session->current_end_frame()) { + + if (!selection->tracks.empty()) { + + if ((r = find_next_region (pos, point, 1, selection->tracks, &ontrack)) == 0) { + break; + } + + } else if (clicked_trackview) { + + TrackViewList t; + t.push_back (clicked_trackview); + + if ((r = find_next_region (pos, point, 1, t, &ontrack)) == 0) { + break; + } + + } else { + + if ((r = find_next_region (pos, point, 1, track_views, &ontrack)) == 0) { + break; + } + } + + jack_nframes_t rpos; + + switch (snap_type) { + case SnapToRegionStart: + rpos = r->first_frame(); + break; + case SnapToRegionEnd: + rpos = r->last_frame(); + break; + case SnapToRegionSync: + rpos = r->adjust_to_sync (r->first_frame()); + break; + + case SnapToRegionBoundary: + rpos = r->last_frame(); + break; + default: + break; + } + + float speed = 1.0f; + AudioTimeAxisView *atav; + + if ( ontrack != 0 && (atav = dynamic_cast(ontrack)) != 0 ) { + if (atav->get_diskstream() != 0) { + speed = atav->get_diskstream()->speed(); + } + } + + rpos = (jack_nframes_t) floor ( (float) rpos / speed ); + + if (region_boundary_cache.empty() || rpos != region_boundary_cache.back()) { + if (snap_type == SnapToRegionBoundary) { + region_boundary_cache.push_back (r->first_frame()); + } + region_boundary_cache.push_back (rpos); + } + + pos = rpos + 1; + } +} + +Region* +Editor::find_next_region (jack_nframes_t frame, RegionPoint point, int32_t dir, TrackViewList& tracks, TimeAxisView **ontrack) +{ + TrackViewList::iterator i; + jack_nframes_t closest = max_frames; + Region* ret = 0; + jack_nframes_t rpos = 0; + + float track_speed; + jack_nframes_t track_frame; + AudioTimeAxisView *atav; + + for (i = tracks.begin(); i != tracks.end(); ++i) { + + jack_nframes_t distance; + Region* r; + + track_speed = 1.0f; + if ( (atav = dynamic_cast(*i)) != 0 ) { + if (atav->get_diskstream()!=0) + track_speed = atav->get_diskstream()->speed(); + } + + track_frame = (jack_nframes_t) floor ( (float) frame * track_speed ); + + if ((r = (*i)->find_next_region (track_frame, point, dir)) == 0) { + continue; + } + + switch (point) { + case Start: + rpos = r->first_frame (); + break; + + case End: + rpos = r->last_frame (); + break; + + case SyncPoint: + rpos = r->adjust_to_sync (r->first_frame()); + break; + } + // rpos is a "track frame", converting it to "time frame" + rpos = (jack_nframes_t) floor ( (float) rpos / track_speed ); + + if (rpos > frame) { + distance = rpos - frame; + } else { + distance = frame - rpos; + } + + if (distance < closest) { + closest = distance; + if (ontrack != 0) + *ontrack = (*i); + ret = r; + } + } + + return ret; +} + +void +Editor::cursor_to_region_point (Cursor* cursor, RegionPoint point, int32_t dir) +{ + Region* r; + jack_nframes_t pos = cursor->current_frame; + + if (!session) { + return; + } + + TimeAxisView *ontrack = 0; + + // so we don't find the current region again.. + if (dir>0 || pos>0) + pos+=dir; + + if (!selection->tracks.empty()) { + + r = find_next_region (pos, point, dir, selection->tracks, &ontrack); + + } else if (clicked_trackview) { + + TrackViewList t; + t.push_back (clicked_trackview); + + r = find_next_region (pos, point, dir, t, &ontrack); + + } else { + + r = find_next_region (pos, point, dir, track_views, &ontrack); + } + + if (r == 0) { + return; + } + + switch (point){ + case Start: + pos = r->first_frame (); + break; + + case End: + pos = r->last_frame (); + break; + + case SyncPoint: + pos = r->adjust_to_sync (r->first_frame()); + break; + } + + float speed = 1.0f; + AudioTimeAxisView *atav; + + if ( ontrack != 0 && (atav = dynamic_cast(ontrack)) != 0 ) { + if (atav->get_diskstream() != 0) { + speed = atav->get_diskstream()->speed(); + } + } + + pos = (jack_nframes_t) floor ( (float) pos / speed ); + + + if (cursor == playhead_cursor) { + session->request_locate (pos); + } else { + cursor->set_position (pos); + } +} + +void +Editor::cursor_to_next_region_point (Cursor* cursor, RegionPoint point) +{ + cursor_to_region_point (cursor, point, 1); +} + +void +Editor::cursor_to_previous_region_point (Cursor* cursor, RegionPoint point) +{ + cursor_to_region_point (cursor, point, -1); +} + +void +Editor::cursor_to_selection_start (Cursor *cursor) +{ + jack_nframes_t pos = 0; + switch (mouse_mode) { + case MouseObject: + if (!selection->audio_regions.empty()) { + pos = selection->audio_regions.start(); + } + break; + + case MouseRange: + if (!selection->time.empty()) { + pos = selection->time.start (); + } + break; + + default: + return; + } + + if (cursor == playhead_cursor) { + session->request_locate (pos); + } else { + cursor->set_position (pos); + } +} + +void +Editor::cursor_to_selection_end (Cursor *cursor) +{ + jack_nframes_t pos = 0; + + switch (mouse_mode) { + case MouseObject: + if (!selection->audio_regions.empty()) { + pos = selection->audio_regions.end_frame(); + } + break; + + case MouseRange: + if (!selection->time.empty()) { + pos = selection->time.end_frame (); + } + break; + + default: + return; + } + + if (cursor == playhead_cursor) { + session->request_locate (pos); + } else { + cursor->set_position (pos); + } +} + +void +Editor::playhead_backward () +{ + jack_nframes_t pos; + jack_nframes_t cnt; + float prefix; + bool was_floating; + + if (get_prefix (prefix, was_floating)) { + cnt = 1; + } else { + if (was_floating) { + cnt = (jack_nframes_t) floor (prefix * session->frame_rate ()); + } else { + cnt = (jack_nframes_t) prefix; + } + } + + pos = playhead_cursor->current_frame; + + if ((jack_nframes_t) pos < cnt) { + pos = 0; + } else { + pos -= cnt; + } + + /* XXX this is completely insane. with the current buffering + design, we'll force a complete track buffer flush and + reload, just to move 1 sample !!! + */ + + session->request_locate (pos); +} + +void +Editor::playhead_forward () +{ + jack_nframes_t pos; + jack_nframes_t cnt; + bool was_floating; + float prefix; + + if (get_prefix (prefix, was_floating)) { + cnt = 1; + } else { + if (was_floating) { + cnt = (jack_nframes_t) floor (prefix * session->frame_rate ()); + } else { + cnt = (jack_nframes_t) floor (prefix); + } + } + + pos = playhead_cursor->current_frame; + + /* XXX this is completely insane. with the current buffering + design, we'll force a complete track buffer flush and + reload, just to move 1 sample !!! + */ + + session->request_locate (pos+cnt); +} + +void +Editor::cursor_align (bool playhead_to_edit) +{ + if (playhead_to_edit) { + if (session) { + session->request_locate (edit_cursor->current_frame); + } + } else { + edit_cursor->set_position (playhead_cursor->current_frame); + } +} + +void +Editor::edit_cursor_backward () +{ + jack_nframes_t pos; + jack_nframes_t cnt; + float prefix; + bool was_floating; + + if (get_prefix (prefix, was_floating)) { + cnt = 1; + } else { + if (was_floating) { + cnt = (jack_nframes_t) floor (prefix * session->frame_rate ()); + } else { + cnt = (jack_nframes_t) prefix; + } + } + + pos = edit_cursor->current_frame; + + if ((jack_nframes_t) pos < cnt) { + pos = 0; + } else { + pos -= cnt; + } + + edit_cursor->set_position (pos); +} + +void +Editor::edit_cursor_forward () +{ + jack_nframes_t pos; + jack_nframes_t cnt; + bool was_floating; + float prefix; + + if (get_prefix (prefix, was_floating)) { + cnt = 1; + } else { + if (was_floating) { + cnt = (jack_nframes_t) floor (prefix * session->frame_rate ()); + } else { + cnt = (jack_nframes_t) floor (prefix); + } + } + + pos = edit_cursor->current_frame; + edit_cursor->set_position (pos+cnt); +} + +void +Editor::goto_frame () +{ + float prefix; + bool was_floating; + jack_nframes_t frame; + + if (get_prefix (prefix, was_floating)) { + return; + } + + if (was_floating) { + frame = (jack_nframes_t) floor (prefix * session->frame_rate()); + } else { + frame = (jack_nframes_t) floor (prefix); + } + + session->request_locate (frame); +} + +void +Editor::scroll_backward (float pages) +{ + jack_nframes_t frame; + jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit); + bool was_floating; + float prefix; + jack_nframes_t cnt; + + if (get_prefix (prefix, was_floating)) { + cnt = (jack_nframes_t) floor (pages * one_page); + } else { + if (was_floating) { + cnt = (jack_nframes_t) floor (prefix * session->frame_rate()); + } else { + cnt = (jack_nframes_t) floor (prefix * one_page); + } + } + + if (leftmost_frame < cnt) { + frame = 0; + } else { + frame = leftmost_frame - cnt; + } + + reposition_x_origin (frame); +} + +void +Editor::scroll_forward (float pages) +{ + jack_nframes_t frame; + jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit); + bool was_floating; + float prefix; + jack_nframes_t cnt; + + if (get_prefix (prefix, was_floating)) { + cnt = (jack_nframes_t) floor (pages * one_page); + } else { + if (was_floating) { + cnt = (jack_nframes_t) floor (prefix * session->frame_rate()); + } else { + cnt = (jack_nframes_t) floor (prefix * one_page); + } + } + + if (ULONG_MAX - cnt < leftmost_frame) { + frame = ULONG_MAX - cnt; + } else { + frame = leftmost_frame + cnt; + } + + reposition_x_origin (frame); +} + +void +Editor::scroll_tracks_down () +{ + float prefix; + bool was_floating; + int cnt; + + if (get_prefix (prefix, was_floating)) { + cnt = 1; + } else { + cnt = (int) floor (prefix); + } + + Gtk::Adjustment *adj = track_canvas_scroller.get_vadjustment(); + adj->set_value (adj->get_value() + (cnt * adj->get_page_size())); +} + +void +Editor::scroll_tracks_up () +{ + float prefix; + bool was_floating; + int cnt; + + if (get_prefix (prefix, was_floating)) { + cnt = 1; + } else { + cnt = (int) floor (prefix); + } + + Gtk::Adjustment *adj = track_canvas_scroller.get_vadjustment(); + adj->set_value (adj->get_value() - (cnt * adj->get_page_size())); +} + +void +Editor::scroll_tracks_down_line () +{ + edit_vscrollbar.default_vmotion (0, 10); +} + +void +Editor::scroll_tracks_up_line () +{ + edit_vscrollbar.default_vmotion (0, -10); +} + +/* ZOOM */ + +void +Editor::temporal_zoom_step (bool coarser) +{ + double nfpu; + + nfpu = frames_per_unit; + + if (coarser) { + nfpu *= 2.0; + } else { + nfpu = max(1.0,(nfpu/2.0)); + } + + temporal_zoom (nfpu); +} + +void +Editor::temporal_zoom (gdouble fpu) +{ + if (!session) return; + + jack_nframes_t current_page = current_page_frames(); + jack_nframes_t current_leftmost = leftmost_frame; + jack_nframes_t current_rightmost; + jack_nframes_t current_center; + jack_nframes_t new_page; + jack_nframes_t leftmost_after_zoom = 0; + double nfpu; + + nfpu = fpu; + + new_page = (jack_nframes_t) floor (canvas_width * nfpu); + + switch (zoom_focus) { + case ZoomFocusLeft: + leftmost_after_zoom = current_leftmost; + break; + + case ZoomFocusRight: + current_rightmost = leftmost_frame + current_page; + if (current_rightmost > new_page) { + leftmost_after_zoom = current_rightmost - new_page; + } else { + leftmost_after_zoom = 0; + } + break; + + case ZoomFocusCenter: + current_center = current_leftmost + (current_page/2); + if (current_center > (new_page/2)) { + leftmost_after_zoom = current_center - (new_page / 2); + } else { + leftmost_after_zoom = 0; + } + break; + + case ZoomFocusPlayhead: + /* try to keep the playhead in the center */ + if (playhead_cursor->current_frame > new_page/2) { + leftmost_after_zoom = playhead_cursor->current_frame - (new_page/2); + } else { + leftmost_after_zoom = 0; + } + break; + + case ZoomFocusEdit: + /* try to keep the edit cursor in the center */ + if (edit_cursor->current_frame > leftmost_frame + (new_page/2)) { + leftmost_after_zoom = edit_cursor->current_frame - (new_page/2); + } else { + leftmost_after_zoom = 0; + } + break; + + } + + // leftmost_after_zoom = min (leftmost_after_zoom, session->current_end_frame()); + +// begin_reversible_command (_("zoom")); +// session->add_undo (bind (slot (*this, &Editor::reposition_and_zoom), current_leftmost, frames_per_unit)); +// session->add_redo (bind (slot (*this, &Editor::reposition_and_zoom), leftmost_after_zoom, nfpu)); +// commit_reversible_command (); + + reposition_and_zoom (leftmost_after_zoom, nfpu); +} + +void +Editor::temporal_zoom_selection () +{ + if (!selection) return; + + if (selection->time.empty()) { + return; + } + + jack_nframes_t start = selection->time[clicked_selection].start; + jack_nframes_t end = selection->time[clicked_selection].end; + + temporal_zoom_by_frame (start, end, "zoom to selection"); +} + +void +Editor::temporal_zoom_session () +{ + if (session) { + temporal_zoom_by_frame (0, session->current_end_frame(), "zoom to session"); + } +} + +void +Editor::temporal_zoom_by_frame (jack_nframes_t start, jack_nframes_t end, string op) +{ + if (!session) return; + + if ((start == 0 && end == 0) || end < start) { + return; + } + + jack_nframes_t range = end - start; + + double new_fpu = (double)range / (double)canvas_width; +// double p2 = 1.0; + +// while (p2 < new_fpu) { +// p2 *= 2.0; +// } +// new_fpu = p2; + + jack_nframes_t new_page = (jack_nframes_t) floor (canvas_width * new_fpu); + jack_nframes_t middle = (jack_nframes_t) floor( (double)start + ((double)range / 2.0f )); + jack_nframes_t new_leftmost = (jack_nframes_t) floor( (double)middle - ((double)new_page/2.0f)); + + if (new_leftmost > middle) new_leftmost = 0; + +// begin_reversible_command (op); +// session->add_undo (bind (slot (*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit)); +// session->add_redo (bind (slot (*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu)); +// commit_reversible_command (); + + reposition_and_zoom (new_leftmost, new_fpu); +} + +void +Editor::temporal_zoom_to_frame (bool coarser, jack_nframes_t frame) +{ + if (!session) return; + + jack_nframes_t range_before = frame - leftmost_frame; + double new_fpu; + + new_fpu = frames_per_unit; + + if (coarser) { + new_fpu *= 2.0; + range_before *= 2; + } else { + new_fpu = max(1.0,(new_fpu/2.0)); + range_before /= 2; + } + + if (new_fpu == frames_per_unit) return; + + jack_nframes_t new_leftmost = frame - range_before; + + if (new_leftmost > frame) new_leftmost = 0; + +// begin_reversible_command (_("zoom to frame")); +// session->add_undo (bind (slot (*this, &Editor::reposition_and_zoom), leftmost_frame, frames_per_unit)); +// session->add_redo (bind (slot (*this, &Editor::reposition_and_zoom), new_leftmost, new_fpu)); +// commit_reversible_command (); + + reposition_and_zoom (new_leftmost, new_fpu); +} + +void +Editor::select_all_in_track (bool add) +{ + list touched; + + if (!clicked_trackview) { + return; + } + + clicked_trackview->get_selectables (0, max_frames, 0, DBL_MAX, touched); + + if (add) { + selection->add (touched); + } else { + selection->set (touched); + } +} + +void +Editor::select_all (bool add) +{ + list touched; + + for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) { + if ((*iter)->hidden()) { + continue; + } + (*iter)->get_selectables (0, max_frames, 0, DBL_MAX, touched); + } + + if (add) { + selection->add (touched); + } else { + selection->set (touched); + } + +} + +void +Editor::invert_selection_in_track () +{ + list touched; + + if (!clicked_trackview) { + return; + } + + clicked_trackview->get_inverted_selectables (*selection, touched); + selection->set (touched); +} + +void +Editor::invert_selection () +{ + list touched; + + for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) { + if ((*iter)->hidden()) { + continue; + } + (*iter)->get_inverted_selectables (*selection, touched); + } + + selection->set (touched); +} + +bool +Editor::select_all_within (jack_nframes_t start, jack_nframes_t end, double top, double bot, bool add) +{ + list touched; + + for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) { + if ((*iter)->hidden()) { + continue; + } + (*iter)->get_selectables (start, end, top, bot, touched); + } + + if (add) { + selection->add (touched); + } else { + selection->set (touched); + } + + return !touched.empty(); +} + +void +Editor::set_selection_from_punch() +{ + Location* location; + + if ((location = session->locations()->auto_punch_location()) == 0) { + return; + } + + set_selection_from_range (*location); +} + +void +Editor::set_selection_from_loop() +{ + Location* location; + + if ((location = session->locations()->auto_loop_location()) == 0) { + return; + } + + set_selection_from_range (*location); +} + +void +Editor::set_selection_from_range (Location& range) +{ + if (clicked_trackview == 0) { + return; + } + + begin_reversible_command (_("set selection from range")); + selection->set (0, range.start(), range.end()); + commit_reversible_command (); +} + +void +Editor::amplitude_zoom_step (bool in) +{ + gdouble zoom = 1.0; + + if (in) { + zoom *= 2.0; + } else { + if (zoom > 2.0) { + zoom /= 2.0; + } else { + zoom = 1.0; + } + } + +#ifdef FIX_FOR_CANVAS + /* XXX DO SOMETHING */ +#endif +} + + +/* DELETION */ + + +void +Editor::delete_sample_forward () +{ +} + +void +Editor::delete_sample_backward () +{ +} + +void +Editor::delete_screen () +{ +} + +/* SEARCH */ + +void +Editor::search_backwards () +{ + /* what ? */ +} + +void +Editor::search_forwards () +{ + /* what ? */ +} + +/* MARKS */ + +void +Editor::jump_forward_to_mark () +{ + if (!session) { + return; + } + + Location *location = session->locations()->first_location_after (playhead_cursor->current_frame); + + if (location) { + session->request_locate (location->start(), session->transport_rolling()); + } else { + session->request_locate (session->current_end_frame()); + } +} + +void +Editor::jump_backward_to_mark () +{ + if (!session) { + return; + } + + Location *location = session->locations()->first_location_before (playhead_cursor->current_frame); + + if (location) { + session->request_locate (location->start(), session->transport_rolling()); + } else { + session->request_locate (0); + } +} + +void +Editor::set_mark () +{ + jack_nframes_t pos; + float prefix; + bool was_floating; + + if (get_prefix (prefix, was_floating)) { + pos = session->audible_frame (); + } else { + if (was_floating) { + pos = (jack_nframes_t) floor (prefix * session->frame_rate ()); + } else { + pos = (jack_nframes_t) floor (prefix); + } + } + + session->locations()->add (new Location (pos, 0, "mark", Location::IsMark), true); +} + +void +Editor::clear_markers () +{ + if (session) { + session->begin_reversible_command (_("clear markers")); + session->add_undo (session->locations()->get_memento()); + session->locations()->clear_markers (); + session->add_redo_no_execute (session->locations()->get_memento()); + session->commit_reversible_command (); + } +} + +void +Editor::clear_ranges () +{ + if (session) { + session->begin_reversible_command (_("clear ranges")); + session->add_undo (session->locations()->get_memento()); + + Location * looploc = session->locations()->auto_loop_location(); + Location * punchloc = session->locations()->auto_punch_location(); + + session->locations()->clear_ranges (); + // re-add these + if (looploc) session->locations()->add (looploc); + if (punchloc) session->locations()->add (punchloc); + + session->add_redo_no_execute (session->locations()->get_memento()); + session->commit_reversible_command (); + } +} + +void +Editor::clear_locations () +{ + session->begin_reversible_command (_("clear locations")); + session->add_undo (session->locations()->get_memento()); + session->locations()->clear (); + session->add_redo_no_execute (session->locations()->get_memento()); + session->commit_reversible_command (); + session->locations()->clear (); +} + +/* INSERT/REPLACE */ + +void +Editor::insert_region_list_drag (AudioRegion& region) +{ + gint x, y; + double wx, wy; + double cx, cy; + TimeAxisView *tv; + jack_nframes_t where; + AudioTimeAxisView *atv = 0; + Playlist *playlist; + + track_canvas->get_pointer (x, y); + + gtk_canvas_window_to_world (GTK_CANVAS(track_gtk_canvas), x, y, &wx, &wy); + + GdkEvent event; + event.type = GDK_BUTTON_RELEASE; + event.button.x = wx; + event.button.y = wy; + + where = event_frame (&event, &cx, &cy); + + if (where < leftmost_frame || where > leftmost_frame + current_page_frames()) { + /* clearly outside canvas area */ + return; + } + + if ((tv = trackview_by_y_position (cy)) == 0) { + return; + } + + if ((atv = dynamic_cast(tv)) == 0) { + return; + } + + if ((playlist = atv->playlist()) == 0) { + return; + } + + snap_to (where); + + begin_reversible_command (_("insert dragged region")); + session->add_undo (playlist->get_memento()); + playlist->add_region (*(new AudioRegion (region)), where, 1.0); + session->add_redo_no_execute (playlist->get_memento()); + commit_reversible_command (); +} + +void +Editor::insert_region_list_selection (float times) +{ + AudioTimeAxisView *tv = 0; + Playlist *playlist; + + if (clicked_audio_trackview != 0) { + tv = clicked_audio_trackview; + } else if (!selection->tracks.empty()) { + if ((tv = dynamic_cast(selection->tracks.front())) == 0) { + return; + } + } else { + return; + } + + if ((playlist = tv->playlist()) == 0) { + return; + } + + Gtk::CTree_Helpers::SelectionList& selected = region_list_display.selection(); + + if (selected.empty()) { + return; + } + + Region* region = reinterpret_cast (selected.front().get_data ()); + + begin_reversible_command (_("insert region")); + session->add_undo (playlist->get_memento()); + playlist->add_region (*(createRegion (*region)), edit_cursor->current_frame, times); + session->add_redo_no_execute (playlist->get_memento()); + commit_reversible_command (); +} + + +/* BUILT-IN EFFECTS */ + +void +Editor::reverse_selection () +{ + +} + +/* GAIN ENVELOPE EDITING */ + +void +Editor::edit_envelope () +{ +} + +/* PLAYBACK */ + +void +Editor::toggle_playback (bool with_abort) +{ + if (!session) { + return; + } + + switch (session->slave_source()) { + case Session::None: + case Session::JACK: + break; + default: + /* transport controlled by the master */ + return; + } + + if (session->is_auditioning()) { + session->cancel_audition (); + return; + } + + if (session->transport_rolling()) { + session->request_stop (with_abort); + if (session->get_auto_loop()) { + session->request_auto_loop (false); + } + } else { + session->request_transport_speed (1.0f); + } +} + +void +Editor::play_from_start () +{ + session->request_locate (0, true); +} + +void +Editor::play_selection () +{ + if (selection->time.empty()) { + return; + } + + session->request_play_range (true); +} + +void +Editor::play_selected_region () +{ + if (!selection->audio_regions.empty()) { + AudioRegionView *rv = *(selection->audio_regions.begin()); + + session->request_bounded_roll (rv->region.position(), rv->region.last_frame()); + } +} + +void +Editor::toggle_loop_playback () +{ + if (session) { + session->request_auto_loop (true); + } +} + +void +Editor::loop_selected_region () +{ + if (!selection->audio_regions.empty()) { + AudioRegionView *rv = *(selection->audio_regions.begin()); + Location* tll; + + if ((tll = transport_loop_location()) != 0) { + + tll->set (rv->region.position(), rv->region.last_frame()); + + // enable looping, reposition and start rolling + + session->request_auto_loop (true); + session->request_locate (tll->start(), false); + session->request_transport_speed (1.0f); + } + } +} + +void +Editor::play_location (Location& location) +{ + if (location.start() <= location.end()) { + return; + } + + session->request_bounded_roll (location.start(), location.end()); +} + +void +Editor::loop_location (Location& location) +{ + if (location.start() <= location.end()) { + return; + } + + Location* tll; + + if ((tll = transport_loop_location()) != 0) { + tll->set (location.start(), location.end()); + + // enable looping, reposition and start rolling + session->request_auto_loop (true); + session->request_locate (tll->start(), true); + } +} + +void +Editor::toggle_region_mute () +{ + if (clicked_regionview) { + clicked_regionview->region.set_muted (!clicked_regionview->region.muted()); + } else if (!selection->audio_regions.empty()) { + bool yn = ! (*selection->audio_regions.begin())->region.muted(); + selection->foreach_audio_region (&AudioRegion::set_muted, yn); + } +} + +void +Editor::toggle_region_opaque () +{ + if (clicked_regionview) { + clicked_regionview->region.set_opaque (!clicked_regionview->region.opaque()); + } else if (!selection->audio_regions.empty()) { + bool yn = ! (*selection->audio_regions.begin())->region.opaque(); + selection->foreach_audio_region (&Region::set_opaque, yn); + } +} + +void +Editor::raise_region () +{ + selection->foreach_audio_region (&Region::raise); +} + +void +Editor::raise_region_to_top () +{ + selection->foreach_audio_region (&Region::raise_to_top); +} + +void +Editor::lower_region () +{ + selection->foreach_audio_region (&Region::lower); +} + +void +Editor::lower_region_to_bottom () +{ + selection->foreach_audio_region (&Region::lower_to_bottom); +} + +void +Editor::edit_region () +{ + if (clicked_regionview == 0) { + return; + } + + clicked_regionview->show_region_editor (); +} + +void +Editor::rename_region () +{ + Dialog dialog; + Entry entry; + Button ok_button (_("OK")); + Button cancel_button (_("Cancel")); + + if (selection->audio_regions.empty()) { + return; + } + + dialog.set_title (_("ardour: rename region")); + dialog.set_name ("RegionRenameWindow"); + dialog.set_usize (300, -1); + dialog.set_position (GTK_WIN_POS_MOUSE); + dialog.set_modal (true); + + dialog.get_vbox()->set_border_width (10); + dialog.get_vbox()->pack_start (entry); + dialog.get_action_area()->pack_start (ok_button); + dialog.get_action_area()->pack_start (cancel_button); + + entry.set_name ("RegionNameDisplay"); + ok_button.set_name ("EditorGTKButton"); + cancel_button.set_name ("EditorGTKButton"); + + region_renamed = false; + + entry.activate.connect (bind (slot (*this, &Editor::rename_region_finished), true)); + ok_button.clicked.connect (bind (slot (*this, &Editor::rename_region_finished), true)); + cancel_button.clicked.connect (bind (slot (*this, &Editor::rename_region_finished), false)); + + /* recurse */ + + dialog.show_all (); + ARDOUR_UI::instance()->allow_focus (true); + Main::run (); + ARDOUR_UI::instance()->allow_focus (false); + + if (region_renamed) { + (*selection->audio_regions.begin())->region.set_name (entry.get_text()); + redisplay_regions (); + } +} + +void +Editor::rename_region_finished (bool status) + +{ + region_renamed = status; + Main::quit (); +} + +void +Editor::audition_playlist_region_via_route (AudioRegion& region, Route& route) +{ + if (session->is_auditioning()) { + session->cancel_audition (); + } + + // note: some potential for creativity here, because region doesn't + // have to belong to the playlist that Route is handling + + // bool was_soloed = route.soloed(); + + route.set_solo (true, this); + + session->request_bounded_roll (region.position(), region.position() + region.length()); + + /* XXX how to unset the solo state ? */ +} + +void +Editor::audition_selected_region () +{ + if (!selection->audio_regions.empty()) { + AudioRegionView* rv = *(selection->audio_regions.begin()); + session->audition_region (rv->region); + } +} + +void +Editor::audition_playlist_region_standalone (AudioRegion& region) +{ + session->audition_region (region); +} + +void +Editor::build_interthread_progress_window () +{ + interthread_progress_window = new ArdourDialog (X_("interthread progress")); + + interthread_progress_bar.set_orientation (GTK_PROGRESS_LEFT_TO_RIGHT); + + interthread_progress_vbox.set_border_width (10); + interthread_progress_vbox.set_spacing (5); + interthread_progress_vbox.pack_start (interthread_progress_label, false, false); + interthread_progress_vbox.pack_start (interthread_progress_bar,false, false); + interthread_progress_vbox.pack_start (interthread_cancel_button,false, false); + + interthread_cancel_button.add (interthread_cancel_label); + + interthread_cancel_button.clicked.connect (slot (*this, &Editor::interthread_cancel_clicked)); + + interthread_progress_window->set_modal (true); + interthread_progress_window->set_default_size (200, 100); + interthread_progress_window->add (interthread_progress_vbox); +} + +void +Editor::interthread_cancel_clicked () +{ + if (current_interthread_info) { + current_interthread_info->cancel = true; + } +} + +void * +Editor::_import_thread (void *arg) +{ + PBD::ThreadCreated (pthread_self(), X_("Import")); + + Editor *ed = (Editor *) arg; + return ed->import_thread (); +} + +void * +Editor::import_thread () +{ + session->import_audiofile (import_status); + return 0; +} + +gint +Editor::import_progress_timeout (void *arg) +{ + interthread_progress_label.set_text (import_status.doing_what); + + if (import_status.freeze) { + interthread_cancel_button.set_sensitive(false); + } else { + interthread_cancel_button.set_sensitive(true); + } + + if (import_status.doing_what == "building peak files") { + interthread_progress_bar.set_activity_mode (true); + return FALSE; + } else { + interthread_progress_bar.set_percentage (import_status.progress); + } + + return !(import_status.done || import_status.cancel); +} + +void +Editor::import_audio (bool as_tracks) +{ + if (session == 0) { + warning << _("You can't import an audiofile until you have a session loaded.") << endmsg; + return; + } + + SoundFileSelector& sfdb (ARDOUR_UI::instance()->get_sfdb_window()); + SigC::Connection c; + string str; + + if (as_tracks) { + c = sfdb.Action.connect (bind (slot (*this, &Editor::do_import), true)); + str =_("Import selected as tracks"); + } else { + c = sfdb.Action.connect (bind (slot (*this, &Editor::do_import), false)); + str = _("Import selected to region list"); + } + + sfdb.run (str, true); + c.disconnect (); +} + +void +Editor::catch_new_audio_region (AudioRegion* ar) +{ + last_audio_region = ar; +} + +void +Editor::do_import (vector paths, bool split, bool as_tracks) +{ + SigC::Connection c; + + /* SFDB sets "multichan" to true to indicate "split channels" + so reverse the setting to match the way libardour + interprets it. + */ + + import_status.multichan = !split; + + if (interthread_progress_window == 0) { + build_interthread_progress_window (); + } + + interthread_progress_window->set_title (_("ardour: audio import in progress")); + interthread_progress_window->set_position (GTK_WIN_POS_MOUSE); + interthread_progress_window->show_all (); + interthread_progress_bar.set_percentage (0.0f); + interthread_cancel_label.set_text (_("Cancel Import")); + current_interthread_info = &import_status; + + c = session->AudioRegionAdded.connect (slot (*this, &Editor::catch_new_audio_region)); + + for (vector::iterator i = paths.begin(); i != paths.end(); ++i ) { + + interthread_progress_window->set_title (compose (_("ardour: importing %1"), (*i))); + + import_status.pathname = (*i); + import_status.done = false; + import_status.cancel = false; + import_status.freeze = false; + import_status.done = 0.0; + + interthread_progress_connection = + Gtk::Main::timeout.connect (bind (slot (*this, &Editor::import_progress_timeout), (gpointer) 0), 100); + + last_audio_region = 0; + + pthread_create_and_store ("import", &import_status.thread, 0, _import_thread, this); + pthread_detach (import_status.thread); + + while (!(import_status.done || import_status.cancel)) { + gtk_main_iteration (); + } + + import_status.done = true; + interthread_progress_connection.disconnect (); + + if (as_tracks && last_audio_region != 0) { + uint32_t channels = last_audio_region->n_channels(); + + AudioTrack* at = session->new_audio_track (channels, channels); + AudioRegion* copy = new AudioRegion (*last_audio_region); + at->disk_stream().playlist()->add_region (*copy, 0); + } + } + + c.disconnect (); + interthread_progress_window->hide_all (); +} + +int +Editor::reject_because_rate_differs (string path, SF_INFO& finfo, string action, bool multiple_pending) +{ + if (!session) { + return 1; + } + + if (finfo.samplerate != (int) session->frame_rate()) { + vector choices; + + choices.push_back (compose (_("%1 it anyway"), action)); + + if (multiple_pending) { + /* XXX assumptions about sentence structure + here for translators. Sorry. + */ + choices.push_back (compose (_("Don't %1 it"), action)); + choices.push_back (compose (_("%1 all without questions"), action)); + choices.push_back (_("Cancel entire import")); + } else { + choices.push_back (_("Cancel")); + } + + Gtkmmext::Choice rate_choice ( + compose (_("%1\nThis audiofile's sample rate doesn't match the session sample rate!"), path), + choices); + + rate_choice.chosen.connect (Main::quit.slot()); + rate_choice.show_all (); + + Main::run (); + + switch (rate_choice.get_choice()) { + case 0: /* do it anyway */ + return 0; + case 1: /* don't import this one */ + return 1; + case 2: /* do the rest without asking */ + return -1; + case 3: /* stop a multi-file import */ + default: + return -2; + } + } + + return 0; +} + +void +Editor::embed_audio () +{ + if (session == 0) { + warning << _("You can't embed an audiofile until you have a session loaded.") << endmsg; + return; + } + + SoundFileSelector& sfdb (ARDOUR_UI::instance()->get_sfdb_window()); + SigC::Connection c = sfdb.Action.connect (slot (*this, &Editor::do_embed_sndfiles)); + + sfdb.run (_("Add to External Region list"), true); + + c.disconnect (); +} + +void +Editor::do_embed_sndfiles (vector paths, bool split) +{ + bool multiple_files = paths.size() > 1; + bool check_sample_rate = true; + + for (vector::iterator i = paths.begin(); i != paths.end(); ++i) { + embed_sndfile (*i, split, multiple_files, check_sample_rate); + } + + session->save_state (""); +} + +void +Editor::embed_sndfile (string path, bool split, bool multiple_files, bool& check_sample_rate) +{ + SndFileSource *source = 0; /* keep g++ quiet */ + AudioRegion::SourceList sources; + string idspec; + string linked_path; + SNDFILE *sf; + SF_INFO finfo; + + /* lets see if we can link it into the session */ + + linked_path = session->sound_dir(); + linked_path += PBD::basename (path); + + if (link (path.c_str(), linked_path.c_str()) == 0) { + + /* there are many reasons why link(2) might have failed. + but if it succeeds, we now have a link in the + session sound dir that will protect against + unlinking of the original path. nice. + */ + + path = linked_path; + } + + memset (&finfo, 0, sizeof(finfo)); + + /* note that we temporarily truncated _id at the colon */ + + if ((sf = sf_open (path.c_str(), SFM_READ, &finfo)) == 0) { + char errbuf[256]; + sf_error_str (0, errbuf, sizeof (errbuf) - 1); + error << compose(_("Editor: cannot open file \"%1\" (%2)"), selection, errbuf) << endmsg; + return; + } + sf_close (sf); + sf = 0; + + if (check_sample_rate) { + switch (reject_because_rate_differs (path, finfo, "Embed", multiple_files)) { + case 0: + break; + case 1: + return; + case -1: + check_sample_rate = false; + break; + + case -2: + default: + return; + } + } + + track_canvas_scroller.get_window().set_cursor (GDK_WATCH); + ARDOUR_UI::instance()->flush_pending (); + + /* make the proper number of channels in the region */ + + for (int n=0; n < finfo.channels; ++n) + { + idspec = path; + idspec += compose(":%1", n); + + try { + source = new SndFileSource (idspec.c_str()); + sources.push_back(source); + } + + catch (failed_constructor& err) { + error << compose(_("could not open %1"), path) << endmsg; + goto out; + } + + ARDOUR_UI::instance()->flush_pending (); + } + + if (sources.size() > 0) { + + string region_name = PBD::basename_nosuffix (path); + region_name += "-0"; + + /* The created region isn't dropped. It emits a signal + that is picked up by the session. + */ + + new AudioRegion (sources, 0, sources[0]->length(), region_name, 0, + Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External)); + + /* make sure we can see it in the list */ + + Gtk::CTree_Helpers::RowList::iterator external_node; + external_node = region_list_display.rows().begin(); + ++external_node; /* its the second node, always */ + external_node->expand_recursive (); + + ARDOUR_UI::instance()->flush_pending (); + } + + out: + track_canvas_scroller.get_window().set_cursor (current_canvas_cursor); +} + +void +Editor::insert_sndfile (bool as_tracks) +{ + SoundFileSelector& sfdb (ARDOUR_UI::instance()->get_sfdb_window()); + SigC::Connection c; + string str; + + if (as_tracks) { + + c = sfdb.Action.connect (slot (*this, &Editor::insert_paths_as_new_tracks)); + str = _("Insert selected as new tracks"); + + } else { + + jack_nframes_t pos; + + if (clicked_audio_trackview == 0) { + return; + } + + if (ensure_cursor (&pos)) { + return; + } + + c = sfdb.Action.connect (bind (slot (*this, &Editor::do_insert_sndfile), pos)); + str = _("Insert selected"); + } + + sfdb.run (str, false); + c.disconnect (); +} + +void +Editor::insert_paths_as_new_tracks (vector paths, bool split) +{ + SNDFILE *sf; + SF_INFO finfo; + bool multiple_files; + bool check_sample_rate = true; + + multiple_files = paths.size() > 1; + + for (vector::iterator p = paths.begin(); p != paths.end(); ++p) { + + memset (&finfo, 0, sizeof(finfo)); + + if ((sf = sf_open ((*p).c_str(), SFM_READ, &finfo)) == 0) { + char errbuf[256]; + sf_error_str (0, errbuf, sizeof (errbuf) - 1); + error << compose(_("Editor: cannot open file \"%1\" (%2)"), (*p), errbuf) << endmsg; + continue; + } + + sf_close (sf); + sf = 0; + + /* add a new track */ + + if (check_sample_rate) { + switch (reject_because_rate_differs (*p, finfo, "Insert", multiple_files)) { + case 0: + break; + case 1: + continue; + case -1: + check_sample_rate = false; + break; + + case -2: + return; + } + } + + uint32_t input_chan = finfo.channels; + uint32_t output_chan; + + if (session->get_output_auto_connect() & Session::AutoConnectMaster) { + output_chan = (session->master_out() ? session->master_out()->n_inputs() : input_chan); + } else { + output_chan = input_chan; + } + + (void) session->new_audio_track (input_chan, output_chan); + + + /* get the last (most recently added) track view */ + + AudioTimeAxisView* tv; + + if ((tv = dynamic_cast(track_views.back())) == 0) { + fatal << _("programming error: ") + << X_("last trackview after new_audio_track is not an audio track!") + << endmsg; + /*NOTREACHED*/ + } + + jack_nframes_t pos = 0; + insert_sndfile_into (*p, true, tv, pos, false); + } +} + +void +Editor::do_insert_sndfile (vector paths, bool split, jack_nframes_t pos) +{ + for (vector::iterator x = paths.begin(); x != paths.end(); ++x) { + insert_sndfile_into (*x, !split, clicked_audio_trackview, pos); + } +} + +void +Editor::insert_sndfile_into (string path, bool multi, AudioTimeAxisView* tv, jack_nframes_t& pos, bool prompt) +{ + SndFileSource *source = 0; /* keep g++ quiet */ + AudioRegion::SourceList sources; + string idspec; + SNDFILE *sf; + SF_INFO finfo; + + memset (&finfo, 0, sizeof(finfo)); + + /* note that we temporarily truncated _id at the colon */ + + if ((sf = sf_open (path.c_str(), SFM_READ, &finfo)) == 0) { + char errbuf[256]; + sf_error_str (0, errbuf, sizeof (errbuf) - 1); + error << compose(_("Editor: cannot open file \"%1\" (%2)"), path, errbuf) << endmsg; + return; + } + sf_close (sf); + sf = 0; + + if (prompt && (reject_because_rate_differs (path, finfo, "Insert", false) != 0)) { + return; + } + + track_canvas_scroller.get_window().set_cursor (GDK_WATCH); + ARDOUR_UI::instance()->flush_pending (); + + /* make the proper number of channels in the region */ + + for (int n=0; n < finfo.channels; ++n) + { + idspec = path; + idspec += compose(":%1", n); + + try { + source = new SndFileSource (idspec.c_str()); + sources.push_back(source); + } + + catch (failed_constructor& err) { + error << compose(_("could not open %1"), path) << endmsg; + goto out; + } + + ARDOUR_UI::instance()->flush_pending (); + } + + if (sources.size() > 0) { + + string region_name = region_name_from_path (PBD::basename (path)); + + AudioRegion *region = new AudioRegion (sources, 0, sources[0]->length(), region_name, + 0, /* irrelevant these days */ + Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External)); + + begin_reversible_command (_("insert sndfile")); + session->add_undo (tv->playlist()->get_memento()); + tv->playlist()->add_region (*region, pos); + session->add_redo_no_execute (tv->playlist()->get_memento()); + commit_reversible_command (); + + pos += sources[0]->length(); + + ARDOUR_UI::instance()->flush_pending (); + } + + out: + track_canvas_scroller.get_window().set_cursor (current_canvas_cursor); + return; +} + +void +Editor::region_from_selection () +{ + if (clicked_trackview == 0) { + return; + } + + if (selection->time.empty()) { + return; + } + + jack_nframes_t start = selection->time[clicked_selection].start; + jack_nframes_t end = selection->time[clicked_selection].end; + + jack_nframes_t selection_cnt = end - start + 1; + + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + + AudioRegion *region; + AudioRegion *current; + Region* current_r; + Playlist *pl; + + jack_nframes_t internal_start; + string new_name; + + if ((pl = (*i)->playlist()) == 0) { + continue; + } + + if ((current_r = pl->top_region_at (start)) == 0) { + continue; + } + + if ((current = dynamic_cast (current_r)) != 0) { + internal_start = start - current->position(); + session->region_name (new_name, current->name(), true); + region = new AudioRegion (*current, internal_start, selection_cnt, new_name); + } + } +} + +void +Editor::create_region_from_selection (vector& new_regions) +{ + if (selection->time.empty() || selection->tracks.empty()) { + return; + } + + jack_nframes_t start = selection->time[clicked_selection].start; + jack_nframes_t end = selection->time[clicked_selection].end; + + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + + AudioRegion* current; + Region* current_r; + Playlist* playlist; + jack_nframes_t internal_start; + string new_name; + + if ((playlist = (*i)->playlist()) == 0) { + continue; + } + + if ((current_r = playlist->top_region_at(start)) == 0) { + continue; + } + + if ((current = dynamic_cast(current_r)) == 0) { + continue; + } + + internal_start = start - current->position(); + session->region_name (new_name, current->name(), true); + + new_regions.push_back (new AudioRegion (*current, internal_start, end - start + 1, new_name)); + } +} + +void +Editor::split_multichannel_region () +{ + vector v; + + if (!clicked_regionview || clicked_regionview->region.n_channels() < 2) { + return; + } + + clicked_regionview->region.separate_by_channel (*session, v); + + /* nothing else to do, really */ +} + +void +Editor::new_region_from_selection () +{ + region_from_selection (); + cancel_selection (); +} + +void +Editor::separate_region_from_selection () +{ + bool doing_undo = false; + + if (selection->time.empty()) { + return; + } + + Playlist *playlist; + + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast ((*i))) != 0) { + + if (atv->is_audio_track()) { + + if ((playlist = atv->playlist()) != 0) { + if (!doing_undo) { + begin_reversible_command (_("separate")); + doing_undo = true; + } + if (doing_undo) session->add_undo ((playlist)->get_memento()); + + /* XXX need to consider musical time selections here at some point */ + + double speed = atv->get_diskstream()->speed(); + + for (list::iterator t = selection->time.begin(); t != selection->time.end(); ++t) { + playlist->partition ((jack_nframes_t)((*t).start * speed), (jack_nframes_t)((*t).end * speed), true); + } + + if (doing_undo) session->add_redo_no_execute (playlist->get_memento()); + } + } + } + } + + if (doing_undo) commit_reversible_command (); +} + +void +Editor::crop_region_to_selection () +{ + if (selection->time.empty()) { + return; + } + + vector playlists; + Playlist *playlist; + + if (clicked_trackview != 0) { + + if ((playlist = clicked_trackview->playlist()) == 0) { + return; + } + + playlists.push_back (playlist); + + } else { + + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast ((*i))) != 0) { + + if (atv->is_audio_track()) { + + if ((playlist = atv->playlist()) != 0) { + playlists.push_back (playlist); + } + } + } + } + } + + if (!playlists.empty()) { + + jack_nframes_t start; + jack_nframes_t end; + jack_nframes_t cnt; + + begin_reversible_command (_("trim to selection")); + + for (vector::iterator i = playlists.begin(); i != playlists.end(); ++i) { + + Region *region; + + start = selection->time.start(); + + if ((region = (*i)->top_region_at(start)) == 0) { + continue; + } + + /* now adjust lengths to that we do the right thing + if the selection extends beyond the region + */ + + start = max (start, region->position()); + end = min (selection->time.end_frame(), start + region->length() - 1); + cnt = end - start + 1; + + session->add_undo ((*i)->get_memento()); + region->trim_to (start, cnt, this); + session->add_redo_no_execute ((*i)->get_memento()); + } + + commit_reversible_command (); + } +} + +void +Editor::region_fill_track () +{ + jack_nframes_t end; + + if (!session || selection->audio_regions.empty()) { + return; + } + + end = session->current_end_frame (); + + begin_reversible_command (_("region fill")); + + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + + AudioRegion& region ((*i)->region); + Playlist* pl = region.playlist(); + + if (end <= region.last_frame()) { + return; + } + + double times = (double) (end - region.last_frame()) / (double) region.length(); + + if (times == 0) { + return; + } + + session->add_undo (pl->get_memento()); + pl->add_region (*(new AudioRegion (region)), region.last_frame(), times); + session->add_redo_no_execute (pl->get_memento()); + } + + commit_reversible_command (); +} + +void +Editor::region_fill_selection () +{ + if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) { + return; + } + + if (selection->time.empty()) { + return; + } + + Region *region; + + Gtk::CTree_Helpers::SelectionList& selected = region_list_display.selection(); + + if (selected.empty()) { + return; + } + + region = reinterpret_cast (selected.front().get_data()); + + jack_nframes_t start = selection->time[clicked_selection].start; + jack_nframes_t end = selection->time[clicked_selection].end; + + Playlist *playlist; + + if (selection->tracks.empty()) { + return; + } + + jack_nframes_t selection_length = end - start; + float times = (float)selection_length / region->length(); + + begin_reversible_command (_("fill selection")); + + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + + if ((playlist = (*i)->playlist()) == 0) { + continue; + } + + session->add_undo (playlist->get_memento()); + playlist->add_region (*(createRegion (*region)), start, times); + session->add_redo_no_execute (playlist->get_memento()); + } + + commit_reversible_command (); +} + +void +Editor::set_region_sync_from_edit_cursor () +{ + if (clicked_regionview == 0) { + return; + } + + if (!clicked_regionview->region.covers (edit_cursor->current_frame)) { + error << _("Place the edit cursor at the desired sync point") << endmsg; + return; + } + + Region& region (clicked_regionview->region); + + begin_reversible_command (_("set sync from edit cursor")); + session->add_undo (region.playlist()->get_memento()); + region.set_sync_position (edit_cursor->current_frame); + session->add_redo_no_execute (region.playlist()->get_memento()); + commit_reversible_command (); +} + +void +Editor::remove_region_sync () +{ + if (clicked_regionview) { + Region& region (clicked_regionview->region); + begin_reversible_command (_("remove sync")); + session->add_undo (region.playlist()->get_memento()); + region.clear_sync_position (); + session->add_redo_no_execute (region.playlist()->get_memento()); + commit_reversible_command (); + } +} + +void +Editor::naturalize () +{ + if (selection->audio_regions.empty()) { + return; + } + begin_reversible_command (_("naturalize")); + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + session->add_undo ((*i)->region.get_memento()); + (*i)->region.move_to_natural_position (this); + session->add_redo_no_execute ((*i)->region.get_memento()); + } + commit_reversible_command (); +} + +void +Editor::align (RegionPoint what) +{ + align_selection (what, edit_cursor->current_frame); +} + +void +Editor::align_relative (RegionPoint what) +{ + align_selection_relative (what, edit_cursor->current_frame); +} + +struct RegionSortByTime { + bool operator() (const AudioRegionView* a, const AudioRegionView* b) { + return a->region.position() < b->region.position(); + } +}; + +void +Editor::align_selection_relative (RegionPoint point, jack_nframes_t position) +{ + if (selection->audio_regions.empty()) { + return; + } + + jack_nframes_t distance; + jack_nframes_t pos = 0; + int dir; + + list sorted; + selection->audio_regions.by_position (sorted); + Region& r ((*sorted.begin())->region); + + switch (point) { + case Start: + pos = r.first_frame (); + break; + + case End: + pos = r.last_frame(); + break; + + case SyncPoint: + pos = r.adjust_to_sync (r.first_frame()); + break; + } + + if (pos > position) { + distance = pos - position; + dir = -1; + } else { + distance = position - pos; + dir = 1; + } + + begin_reversible_command (_("align selection (relative)")); + + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + + Region& region ((*i)->region); + + session->add_undo (region.playlist()->get_memento()); + + if (dir > 0) { + region.set_position (region.position() + distance, this); + } else { + region.set_position (region.position() - distance, this); + } + + session->add_redo_no_execute (region.playlist()->get_memento()); + + } + + commit_reversible_command (); +} + +void +Editor::align_selection (RegionPoint point, jack_nframes_t position) +{ + if (selection->audio_regions.empty()) { + return; + } + + begin_reversible_command (_("align selection")); + + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + align_region_internal ((*i)->region, point, position); + } + + commit_reversible_command (); +} + +void +Editor::align_region (Region& region, RegionPoint point, jack_nframes_t position) +{ + begin_reversible_command (_("align region")); + align_region_internal (region, point, position); + commit_reversible_command (); +} + +void +Editor::align_region_internal (Region& region, RegionPoint point, jack_nframes_t position) +{ + session->add_undo (region.playlist()->get_memento()); + + switch (point) { + case SyncPoint: + region.set_position (region.adjust_to_sync (position), this); + break; + + case End: + if (position > region.length()) { + region.set_position (position - region.length(), this); + } + break; + + case Start: + region.set_position (position, this); + break; + } + + session->add_redo_no_execute (region.playlist()->get_memento()); +} + +void +Editor::trim_region_to_edit_cursor () +{ + if (clicked_regionview == 0) { + return; + } + + Region& region (clicked_regionview->region); + + float speed = 1.0f; + AudioTimeAxisView *atav; + + if ( clicked_trackview != 0 && (atav = dynamic_cast(clicked_trackview)) != 0 ) { + if (atav->get_diskstream() != 0) { + speed = atav->get_diskstream()->speed(); + } + } + + begin_reversible_command (_("trim to edit")); + session->add_undo (region.playlist()->get_memento()); + region.trim_end ( (jack_nframes_t) floor( (float)edit_cursor->current_frame * speed), this); + session->add_redo_no_execute (region.playlist()->get_memento()); + commit_reversible_command (); +} + +void +Editor::trim_region_from_edit_cursor () +{ + if (clicked_regionview == 0) { + return; + } + + Region& region (clicked_regionview->region); + + float speed = 1.0f; + AudioTimeAxisView *atav; + + if ( clicked_trackview != 0 && (atav = dynamic_cast(clicked_trackview)) != 0 ) { + if (atav->get_diskstream() != 0) { + speed = atav->get_diskstream()->speed(); + } + } + + begin_reversible_command (_("trim to edit")); + session->add_undo (region.playlist()->get_memento()); + region.trim_front ( (jack_nframes_t) floor( (float)edit_cursor->current_frame * speed), this); + session->add_redo_no_execute (region.playlist()->get_memento()); + commit_reversible_command (); +} + +void +Editor::unfreeze_route () +{ + if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) { + return; + } + + clicked_audio_trackview->audio_track()->unfreeze (); +} + +void* +Editor::_freeze_thread (void* arg) +{ + PBD::ThreadCreated (pthread_self(), X_("Freeze")); + return static_cast(arg)->freeze_thread (); +} + +void* +Editor::freeze_thread () +{ + clicked_audio_trackview->audio_track()->freeze (*current_interthread_info); + return 0; +} + +gint +Editor::freeze_progress_timeout (void *arg) +{ + interthread_progress_bar.set_percentage (current_interthread_info->progress); + return !(current_interthread_info->done || current_interthread_info->cancel); +} + +void +Editor::freeze_route () +{ + if (clicked_audio_trackview == 0 || !clicked_audio_trackview->is_audio_track()) { + return; + } + + InterThreadInfo itt; + + if (interthread_progress_window == 0) { + build_interthread_progress_window (); + } + + interthread_progress_window->set_title (_("ardour: freeze")); + interthread_progress_window->set_position (GTK_WIN_POS_MOUSE); + interthread_progress_window->show_all (); + interthread_progress_bar.set_percentage (0.0f); + interthread_progress_label.set_text (""); + interthread_cancel_label.set_text (_("Cancel Freeze")); + current_interthread_info = &itt; + + interthread_progress_connection = + Gtk::Main::timeout.connect (bind (slot (*this, &Editor::freeze_progress_timeout), (gpointer) 0), 100); + + itt.done = false; + itt.cancel = false; + itt.progress = 0.0f; + + pthread_create (&itt.thread, 0, _freeze_thread, this); + + track_canvas_scroller.get_window().set_cursor (GDK_WATCH); + + while (!itt.done && !itt.cancel) { + gtk_main_iteration (); + } + + interthread_progress_connection.disconnect (); + interthread_progress_window->hide_all (); + current_interthread_info = 0; + track_canvas_scroller.get_window().set_cursor (current_canvas_cursor); +} + +void +Editor::bounce_range_selection () +{ + if (selection->time.empty()) { + return; + } + + TrackViewList *views = get_valid_views (selection->time.track, selection->time.group); + + jack_nframes_t start = selection->time[clicked_selection].start; + jack_nframes_t end = selection->time[clicked_selection].end; + jack_nframes_t cnt = end - start + 1; + + begin_reversible_command (_("bounce range")); + + for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) { + + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast (*i)) == 0) { + continue; + } + + Playlist* playlist; + + if ((playlist = atv->playlist()) == 0) { + return; + } + + InterThreadInfo itt; + + itt.done = false; + itt.cancel = false; + itt.progress = false; + + session->add_undo (playlist->get_memento()); + atv->audio_track()->bounce_range (start, cnt, itt); + session->add_redo_no_execute (playlist->get_memento()); + } + + commit_reversible_command (); + + delete views; +} + +void +Editor::cut () +{ + cut_copy (Cut); +} + +void +Editor::copy () +{ + cut_copy (Copy); +} + +void +Editor::cut_copy (CutCopyOp op) +{ + /* only cancel selection if cut/copy is successful.*/ + + string opname; + + switch (op) { + case Cut: + opname = _("cut"); + break; + case Copy: + opname = _("copy"); + break; + case Clear: + opname = _("clear"); + break; + } + + cut_buffer->clear (); + + switch (current_mouse_mode()) { + case MouseObject: + if (!selection->audio_regions.empty() || !selection->points.empty()) { + + begin_reversible_command (opname + _(" objects")); + + if (!selection->audio_regions.empty()) { + + cut_copy_regions (op); + + if (op == Cut) { + selection->clear_audio_regions (); + } + } + + if (!selection->points.empty()) { + cut_copy_points (op); + + if (op == Cut) { + selection->clear_points (); + } + } + + commit_reversible_command (); + } + break; + + case MouseRange: + if (!selection->time.empty()) { + + begin_reversible_command (opname + _(" range")); + cut_copy_ranges (op); + commit_reversible_command (); + + if (op == Cut) { + selection->clear_time (); + } + + } + break; + + default: + break; + } +} + +void +Editor::cut_copy_points (CutCopyOp op) +{ + for (PointSelection::iterator i = selection->points.begin(); i != selection->points.end(); ++i) { + + AutomationTimeAxisView* atv = dynamic_cast(&(*i).track); + + if (atv) { + atv->cut_copy_clear_objects (selection->points, op); + } + } +} + +void +Editor::cut_copy_regions (CutCopyOp op) +{ + typedef map PlaylistMapping; + PlaylistMapping pmap; + jack_nframes_t first_position = max_frames; + set freezelist; + pair::iterator,bool> insert_result; + + for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ++x) { + first_position = min ((*x)->region.position(), first_position); + + if (op == Cut || op == Clear) { + AudioPlaylist *pl = dynamic_cast((*x)->region.playlist()); + if (pl) { + insert_result = freezelist.insert (pl); + if (insert_result.second) { + pl->freeze (); + session->add_undo (pl->get_memento()); + } + } + } + } + + for (AudioRegionSelection::iterator x = selection->audio_regions.begin(); x != selection->audio_regions.end(); ) { + + AudioPlaylist *pl = dynamic_cast((*x)->region.playlist()); + AudioPlaylist* npl; + AudioRegionSelection::iterator tmp; + + tmp = x; + ++tmp; + + if (pl) { + + PlaylistMapping::iterator pi = pmap.find (pl); + + if (pi == pmap.end()) { + npl = new AudioPlaylist (*session, "cutlist", true); + npl->freeze(); + pmap[pl] = npl; + } else { + npl = pi->second; + } + + switch (op) { + case Cut: + npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position); + pl->remove_region (&((*x)->region)); + break; + + case Copy: + npl->add_region (*(new AudioRegion ((*x)->region)), (*x)->region.position() - first_position); + break; + + case Clear: + pl->remove_region (&((*x)->region)); + break; + } + } + + x = tmp; + } + + list foo; + + for (PlaylistMapping::iterator i = pmap.begin(); i != pmap.end(); ++i) { + foo.push_back (i->second); + } + + if (!foo.empty()) { + cut_buffer->set (foo); + } + + for (set::iterator pl = freezelist.begin(); pl != freezelist.end(); ++pl) { + (*pl)->thaw (); + session->add_redo_no_execute ((*pl)->get_memento()); + } +} + +void +Editor::cut_copy_ranges (CutCopyOp op) +{ + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + (*i)->cut_copy_clear (*selection, op); + } +} + +void +Editor::paste (float times) +{ + paste_internal (edit_cursor->current_frame, times); +} + +void +Editor::mouse_paste () +{ + gint x, y; + double wx, wy; + track_canvas->get_pointer (x, y); + + gtk_canvas_window_to_world (GTK_CANVAS(track_gtk_canvas), x, y, &wx, &wy); + + GdkEvent event; + event.type = GDK_BUTTON_RELEASE; + event.button.x = wx; + event.button.y = wy; + + jack_nframes_t where = event_frame (&event, 0, 0); + snap_to (where); + paste_internal (where, 1); +} + +void +Editor::paste_internal (jack_nframes_t position, float times) +{ + bool commit = false; + + if (cut_buffer->empty() || selection->tracks.empty()) { + return; + } + + if (position == max_frames) { + position = edit_cursor->current_frame; + } + + begin_reversible_command (_("paste")); + + TrackSelection::iterator i; + size_t nth; + + for (nth = 0, i = selection->tracks.begin(); i != selection->tracks.end(); ++i, ++nth) { + + /* undo/redo is handled by individual tracks */ + + if ((*i)->paste (position, times, *cut_buffer, nth)) { + commit = true; + } + } + + if (commit) { + commit_reversible_command (); + } +} + +void +Editor::paste_named_selection (float times) +{ + Gtk::CList_Helpers::SelectionList& selected = named_selection_display.selection(); + TrackSelection::iterator i; + + if (selected.empty() || selection->tracks.empty()) { + return; + } + + NamedSelection* ns = static_cast (selected.front()->get_data ()); + list::iterator chunk; + list::iterator tmp; + + chunk = ns->playlists.begin(); + + begin_reversible_command (_("paste chunk")); + + for (i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + + AudioTimeAxisView* atv; + Playlist* pl; + AudioPlaylist* apl; + + if ((atv = dynamic_cast (*i)) == 0) { + continue; + } + + if ((pl = atv->playlist()) == 0) { + continue; + } + + if ((apl = dynamic_cast (pl)) == 0) { + continue; + } + + tmp = chunk; + ++tmp; + + session->add_undo (apl->get_memento()); + apl->paste (**chunk, edit_cursor->current_frame, times); + session->add_redo_no_execute (apl->get_memento()); + + if (tmp != ns->playlists.end()) { + chunk = tmp; + } + } + + commit_reversible_command(); +} + +void +Editor::duplicate_some_regions (AudioRegionSelection& regions, float times) +{ + Playlist *playlist; + + begin_reversible_command (_("duplicate region")); + + for (AudioRegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) { + + Region& r ((*i)->region); + + playlist = (*i)->region.playlist(); + session->add_undo (playlist->get_memento()); + playlist->duplicate (r, r.last_frame(), times); + session->add_redo_no_execute (playlist->get_memento()); + + } + + commit_reversible_command (); +} + +void +Editor::duplicate_selection (float times) +{ + if (selection->time.empty() || selection->tracks.empty()) { + return; + } + + Playlist *playlist; + vector new_regions; + vector::iterator ri; + + create_region_from_selection (new_regions); + + if (new_regions.empty()) { + return; + } + + begin_reversible_command (_("duplicate selection")); + + ri = new_regions.begin(); + + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + if ((playlist = (*i)->playlist()) == 0) { + continue; + } + session->add_undo (playlist->get_memento()); + playlist->duplicate (**ri, selection->time[clicked_selection].end, times); + session->add_redo_no_execute (playlist->get_memento()); + + ++ri; + if (ri == new_regions.end()) { + --ri; + } + } + + commit_reversible_command (); +} + +void +Editor::center_playhead () +{ + float page = canvas_width * frames_per_unit; + + center_screen_internal (playhead_cursor->current_frame, page); +} + +void +Editor::center_edit_cursor () +{ + float page = canvas_width * frames_per_unit; + + center_screen_internal (edit_cursor->current_frame, page); +} + +void +Editor::clear_playlist (Playlist& playlist) +{ + begin_reversible_command (_("clear playlist")); + session->add_undo (playlist.get_memento()); + playlist.clear (); + session->add_redo_no_execute (playlist.get_memento()); + commit_reversible_command (); +} + +void +Editor::nudge_track (bool use_edit_cursor, bool forwards) +{ + Playlist *playlist; + jack_nframes_t distance; + jack_nframes_t next_distance; + jack_nframes_t start; + + if (use_edit_cursor) { + start = edit_cursor->current_frame; + } else { + start = 0; + } + + if ((distance = get_nudge_distance (start, next_distance)) == 0) { + return; + } + + if (selection->tracks.empty()) { + return; + } + + begin_reversible_command (_("nudge track")); + + for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) { + + if ((playlist = (*i)->playlist()) == 0) { + continue; + } + + session->add_undo (playlist->get_memento()); + playlist->nudge_after (start, distance, forwards); + session->add_redo_no_execute (playlist->get_memento()); + } + + commit_reversible_command (); +} + +void +Editor::toggle_xfades_active () +{ + if (session) { + session->set_crossfades_active (!session->get_crossfades_active()); + } +} + +void +Editor::toggle_follow_playhead () +{ + set_follow_playhead (!_follow_playhead); +} + +void +Editor::set_xfade_visibility (bool yn) +{ + +} + +void +Editor::toggle_xfade_visibility () +{ + set_xfade_visibility (!xfade_visibility()); +} + +void +Editor::remove_last_capture () +{ + vector choices; + string prompt; + + if (!session) { + return; + } + + if (Config->get_verify_remove_last_capture()) { + prompt = _("Do you really want to destroy the last capture?" + "\n(This is destructive and cannot be undone)"); + + choices.push_back (_("Yes, destroy it.")); + choices.push_back (_("No, do nothing.")); + + Gtkmmext::Choice prompter (prompt, choices); + + prompter.chosen.connect (Gtk::Main::quit.slot()); + prompter.show_all (); + + Gtk::Main::run (); + + if (prompter.get_choice() == 0) { + session->remove_last_capture (); + } + } else { + session->remove_last_capture(); + } +} + +void +Editor::normalize_region () +{ + if (!session) { + return; + } + + if (selection->audio_regions.empty()) { + return; + } + + begin_reversible_command (_("normalize")); + + track_canvas_scroller.get_window().set_cursor (wait_cursor); + gdk_flush (); + + for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) { + session->add_undo ((*r)->region.get_memento()); + (*r)->region.normalize_to (0.0f); + session->add_redo_no_execute ((*r)->region.get_memento()); + } + + commit_reversible_command (); + gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); +} + + +void +Editor::denormalize_region () +{ + if (!session) { + return; + } + + if (selection->audio_regions.empty()) { + return; + } + + begin_reversible_command ("denormalize"); + + for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ++r) { + session->add_undo ((*r)->region.get_memento()); + (*r)->region.set_scale_amplitude (1.0f); + session->add_redo_no_execute ((*r)->region.get_memento()); + } + + commit_reversible_command (); +} + + +void +Editor::reverse_region () +{ + if (!session) { + return; + } + + Reverse rev (*session); + apply_filter (rev, _("reverse regions")); +} + +void +Editor::apply_filter (AudioFilter& filter, string command) +{ + if (selection->audio_regions.empty()) { + return; + } + + begin_reversible_command (command); + + track_canvas_scroller.get_window().set_cursor (wait_cursor); + gdk_flush (); + + for (AudioRegionSelection::iterator r = selection->audio_regions.begin(); r != selection->audio_regions.end(); ) { + + AudioRegion& region ((*r)->region); + Playlist* playlist = region.playlist(); + + AudioRegionSelection::iterator tmp; + + tmp = r; + ++tmp; + + if (region.apply (filter) == 0) { + + session->add_undo (playlist->get_memento()); + playlist->replace_region (region, *(filter.results.front()), region.position()); + session->add_redo_no_execute (playlist->get_memento()); + } else { + goto out; + } + + r = tmp; + } + + commit_reversible_command (); + selection->audio_regions.clear (); + + out: + gdk_window_set_cursor (track_canvas_scroller.get_window(), current_canvas_cursor); +} + +void +Editor::region_selection_op (void (Region::*pmf)(void)) +{ + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + ((*i)->region.*pmf)(); + } +} + + +void +Editor::region_selection_op (void (Region::*pmf)(void*), void *arg) +{ + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + ((*i)->region.*pmf)(arg); + } +} + +void +Editor::region_selection_op (void (Region::*pmf)(bool), bool yn) +{ + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + ((*i)->region.*pmf)(yn); + } +} + +void +Editor::external_edit_region () +{ + if (!clicked_regionview) { + return; + } + + /* more to come */ +} + +void +Editor::brush (jack_nframes_t pos) +{ + AudioRegionSelection sel; + snap_to (pos); + + if (selection->audio_regions.empty()) { + /* XXX get selection from region list */ + } else { + sel = selection->audio_regions; + } + + if (sel.empty()) { + return; + } + + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + mouse_brush_insert_region ((*i), pos); + } +} + +void +Editor::toggle_gain_envelope_visibility () +{ + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + (*i)->set_envelope_visible (!(*i)->envelope_visible()); + } +} + +void +Editor::toggle_gain_envelope_active () +{ + for (AudioRegionSelection::iterator i = selection->audio_regions.begin(); i != selection->audio_regions.end(); ++i) { + AudioRegion* ar = dynamic_cast(&(*i)->region); + if (ar) { + ar->set_envelope_active (true); + } + } +} diff --git a/gtk2_ardour/editor_region_list.cc b/gtk2_ardour/editor_region_list.cc new file mode 100644 index 0000000000..cd7b1a5995 --- /dev/null +++ b/gtk2_ardour/editor_region_list.cc @@ -0,0 +1,925 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include "editor.h" +#include "editing.h" +#include "ardour_ui.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; +using namespace Editing; + +#define wave_cursor_width 43 +#define wave_cursor_height 61 +#define wave_cursor_x_hot 0 +#define wave_cursor_y_hot 25 +static const gchar wave_cursor_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, +0x03, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, +0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, +0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, +0x02, + 0x02, 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x00, 0x04, 0x00, +0x02, + 0x02, 0x04, 0x00, 0x04, 0x00, 0x02, 0x02, 0x0c, 0x08, 0x0c, 0x00, +0x02, + 0x02, 0x1c, 0x08, 0x0c, 0x00, 0x02, 0x02, 0x1c, 0x08, 0x0c, 0x04, +0x02, + 0x02, 0x3c, 0x18, 0x0c, 0x04, 0x02, 0x02, 0x7c, 0x18, 0x1c, 0x0c, +0x02, + 0x82, 0xfc, 0x38, 0x1c, 0x0c, 0x02, 0xc2, 0xfc, 0x78, 0x3c, 0x1c, +0x02, + 0xe2, 0xfd, 0xf9, 0x7d, 0x1c, 0x02, 0xf2, 0xff, 0xfb, 0xff, 0x1c, +0x02, + 0xfa, 0xff, 0xfb, 0xff, 0x3f, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, +0x03, + 0xfe, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfa, 0xff, 0xff, 0xff, 0x3f, +0x02, + 0xf2, 0xff, 0xfb, 0xfd, 0x3c, 0x02, 0xe2, 0xfd, 0x7b, 0x7c, 0x1c, +0x02, + 0xc2, 0xfc, 0x39, 0x3c, 0x1c, 0x02, 0x82, 0xfc, 0x18, 0x1c, 0x1c, +0x02, + 0x02, 0xfc, 0x18, 0x1c, 0x0c, 0x02, 0x02, 0x7c, 0x18, 0x0c, 0x0c, +0x02, + 0x02, 0x3c, 0x08, 0x0c, 0x04, 0x02, 0x02, 0x1c, 0x08, 0x0c, 0x04, +0x02, + 0x02, 0x1c, 0x08, 0x0c, 0x00, 0x02, 0x02, 0x0c, 0x00, 0x04, 0x00, +0x02, + 0x02, 0x04, 0x00, 0x04, 0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00, +0x02, + 0x02, 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, +0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, +0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, +0x02, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff, +0x03, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +#define wave_cursor_mask_width 43 +#define wave_cursor_mask_height 61 +#define wave_cursor_mask_x_hot 0 +#define wave_cursor_mask_y_hot 25 +static const gchar wave_cursor_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, +0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x08, 0x0c, 0x00, +0x00, + 0x00, 0x1c, 0x08, 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x0c, 0x04, +0x00, + 0x00, 0x3c, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x7c, 0x18, 0x1c, 0x0c, +0x00, + 0x80, 0xfc, 0x38, 0x1c, 0x0c, 0x00, 0xc0, 0xfc, 0x78, 0x3c, 0x1c, +0x00, + 0xe0, 0xfd, 0xf9, 0x7d, 0x1c, 0x00, 0xf0, 0xff, 0xfb, 0xff, 0x1c, +0x00, + 0xf8, 0xff, 0xfb, 0xff, 0x3f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, +0x07, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0x3f, +0x00, + 0xf0, 0xff, 0xfb, 0xfd, 0x3c, 0x00, 0xe0, 0xfd, 0x7b, 0x7c, 0x1c, +0x00, + 0xc0, 0xfc, 0x39, 0x3c, 0x1c, 0x00, 0x80, 0xfc, 0x18, 0x1c, 0x1c, +0x00, + 0x00, 0xfc, 0x18, 0x1c, 0x0c, 0x00, 0x00, 0x7c, 0x18, 0x0c, 0x0c, +0x00, + 0x00, 0x3c, 0x08, 0x0c, 0x04, 0x00, 0x00, 0x1c, 0x08, 0x0c, 0x04, +0x00, + 0x00, 0x1c, 0x08, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00, +0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +GdkCursor *wave_cursor = 0; + +void +Editor::handle_audio_region_removed (AudioRegion* ignored) +{ + redisplay_regions (); +} + +void +Editor::handle_new_audio_region (AudioRegion *region) +{ + /* don't copy region - the one we are being notified + about belongs to the session, and so it will + never be edited. + */ + add_audio_region_to_region_display (region); +} + +void +Editor::region_hidden (Region* r) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Editor::region_hidden), r)); + + redisplay_regions (); +} + +void +Editor::add_audio_region_to_region_display (AudioRegion *region) +{ + using namespace Gtk::CTree_Helpers; + + vector item; + RowList::iterator i; + RowList::iterator tmpi; + string str; + + if (!show_automatic_regions_in_region_list && region->automatic()) { + return; + } + + if (region->hidden()) { + + if (region_list_hidden_node == region_list_display.rows().end()) { + item.clear (); + item.push_back (_("hidden")); + region_list_hidden_node = region_list_display.rows().insert (region_list_display.rows().end(), + Element (item)); + (*region_list_hidden_node).set_data (0); + (*region_list_hidden_node).set_leaf (false); + } + + item.clear (); + if (region->n_channels() > 1) { + str = compose("%1 [%2]", region->name(), region->n_channels()); + item.push_back (str.c_str()); + } else { + item.push_back (region->name().c_str()); + } + + tmpi = region_list_hidden_node->subtree().insert (region_list_hidden_node->subtree().end(), + Element (item)); + (*tmpi).set_data (region); + return; + + } else if (region->whole_file()) { + + item.clear (); + + if (region->source().name()[0] == '/') { // external file + + if (region->whole_file()) { + str = ".../"; + str += PBD::basename_nosuffix (region->source().name()); + } else { + str = region->name(); + } + + } else { + + str = region->name(); + + } + + item.push_back (str.c_str()); + + tmpi = region_list_display.rows().insert (region_list_display.rows().end(), + Element (item)); + + (*tmpi).set_data (region); + (*tmpi).set_leaf (false); + + return; + + } else { + + /* find parent node, add as new child */ + + for (i = region_list_display.rows().begin(); i != region_list_display.rows().end(); ++i) { + + AudioRegion* r = static_cast ((*i).get_data()); + + if (r && r->whole_file()) { + + if (region->source_equivalent (*r)) { + + item.clear (); + + if (region->n_channels() > 1) { + str = compose("%1 [%2]", region->name(), region->n_channels()); + item.push_back (str.c_str()); + } else { + item.push_back (region->name().c_str()); + } + + + tmpi = i->subtree().insert (i->subtree().end(), Element (item)); + (*tmpi).set_data (region); + + return; + } + } + } + } + + item.clear (); + + if (region->n_channels() > 1) { + str = compose("%1 [%2]", region->name(), region->n_channels()); + item.push_back (str.c_str()); + } else { + item.push_back (region->name().c_str()); + } + + tmpi = region_list_display.rows().insert (region_list_display.rows().end(), Element (item)); + (*tmpi).set_data (region); + (*tmpi).set_leaf (true); +} + +void +Editor::insert_into_tmp_audio_regionlist(AudioRegion* region) +{ + /* keep all whole files at the beginning */ + + if (region->whole_file()) { + tmp_audio_region_list.push_front (region); + } else { + tmp_audio_region_list.push_back (region); + } +} + +void +Editor::redisplay_regions () +{ + if (session) { + region_list_display.freeze (); + region_list_clear (); + region_list_hidden_node = region_list_display.rows().end(); + + /* now add everything we have, via a temporary list used to help with + sorting. + */ + + tmp_audio_region_list.clear(); + session->foreach_audio_region (this, &Editor::insert_into_tmp_audio_regionlist); + + for (list::iterator r = tmp_audio_region_list.begin(); r != tmp_audio_region_list.end(); ++r) { + add_audio_region_to_region_display (*r); + } + + region_list_display.sort (); + region_list_display.thaw (); + } +} + +void +Editor::region_list_clear () +{ + /* ---------------------------------------- */ + /* XXX MAKE ME A FUNCTION (no CTree::clear() in gtkmm 1.2) */ + + gtk_ctree_remove_node (region_list_display.gtkobj(), NULL); + + /* ---------------------------------------- */ +} + +void +Editor::region_list_column_click (gint col) +{ + bool sensitive; + + if (region_list_menu == 0) { + build_region_list_menu (); + } + + if (region_list_display.selection().size() != 0) { + sensitive = true; + } else { + sensitive = false; + } + + for (vector::iterator i = rl_context_menu_region_items.begin(); i != rl_context_menu_region_items.end(); ++i) { + (*i)->set_sensitive (sensitive); + } + + region_list_menu->popup (0, 0); +} + +void +Editor::build_region_list_menu () +{ + using namespace Gtk::Menu_Helpers; + + region_list_menu = new Menu; + + MenuList& items = region_list_menu->items(); + region_list_menu->set_name ("ArdourContextMenu"); + + items.push_back (MenuElem (_("Audition"), slot (*this, &Editor::audition_region_from_region_list))); + rl_context_menu_region_items.push_back (items.back()); + items.push_back (MenuElem (_("Hide"), slot (*this, &Editor::hide_region_from_region_list))); + rl_context_menu_region_items.push_back (items.back()); + items.push_back (MenuElem (_("Remove"), slot (*this, &Editor::remove_region_from_region_list))); + rl_context_menu_region_items.push_back (items.back()); + + + items.push_back (SeparatorElem()); + + + // items.push_back (MenuElem (_("Find"))); + items.push_back (CheckMenuElem (_("Show all"), slot (*this, &Editor::toggle_full_region_list))); + toggle_full_region_list_item = static_cast (items.back()); + + Gtk::Menu *sort_menu = manage (new Menu); + MenuList& sort_items = sort_menu->items(); + sort_menu->set_name ("ArdourContextMenu"); + RadioMenuItem::Group sort_order_group; + RadioMenuItem::Group sort_type_group; + + sort_items.push_back (RadioMenuElem (sort_order_group, _("Ascending"), + bind (slot (*this, &Editor::reset_region_list_sort_direction), true))); + sort_items.push_back (RadioMenuElem (sort_order_group, _("Descending"), + bind (slot (*this, &Editor::reset_region_list_sort_direction), false))); + sort_items.push_back (SeparatorElem()); + + sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Name"), + bind (slot (*this, &Editor::reset_region_list_sort_type), ByName))); + sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Length"), + bind (slot (*this, &Editor::reset_region_list_sort_type), ByLength))); + sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Position"), + bind (slot (*this, &Editor::reset_region_list_sort_type), ByPosition))); + sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Timestamp"), + bind (slot (*this, &Editor::reset_region_list_sort_type), ByTimestamp))); + sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Start in File"), + bind (slot (*this, &Editor::reset_region_list_sort_type), ByStartInFile))); + sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region End in File"), + bind (slot (*this, &Editor::reset_region_list_sort_type), ByEndInFile))); + sort_items.push_back (RadioMenuElem (sort_type_group, _("By Source File Name"), + bind (slot (*this, &Editor::reset_region_list_sort_type), BySourceFileName))); + sort_items.push_back (RadioMenuElem (sort_type_group, _("By Source File Length"), + bind (slot (*this, &Editor::reset_region_list_sort_type), BySourceFileLength))); + sort_items.push_back (RadioMenuElem (sort_type_group, _("By Source File Creation Date"), + bind (slot (*this, &Editor::reset_region_list_sort_type), BySourceFileCreationDate))); + sort_items.push_back (RadioMenuElem (sort_type_group, _("By Source Filesystem"), + bind (slot (*this, &Editor::reset_region_list_sort_type), BySourceFileFS))); + + items.push_back (MenuElem (_("Sorting"), *sort_menu)); + items.push_back (SeparatorElem()); + +// items.push_back (CheckMenuElem (_("Display Automatic Regions"), slot (*this, &Editor::toggle_show_auto_regions))); +// toggle_auto_regions_item = static_cast (items.back()); +// toggle_auto_regions_item->set_active (show_automatic_regions_in_region_list); +// items.push_back (SeparatorElem()); + + items.push_back (MenuElem (_("Import audio (copy)"), bind (slot (*this, &Editor::import_audio), false))); + import_audio_item = items.back(); + if (!session) { + import_audio_item->set_sensitive (false); + } + items.push_back (MenuElem (_("Embed audio (link)"), slot (*this, &Editor::embed_audio))); + embed_audio_item = items.back(); + if (!session) { + embed_audio_item->set_sensitive (false); + } +} + +void +Editor::toggle_show_auto_regions () +{ + //show_automatic_regions_in_region_list = toggle_auto_regions_item->get_active(); + show_automatic_regions_in_region_list = true; + redisplay_regions (); +} + +void +Editor::toggle_full_region_list () +{ + region_list_display.freeze (); + if (toggle_full_region_list_item->get_active()) { + for (CTree_Helpers::RowIterator r = region_list_display.rows().begin(); r != region_list_display.rows().end(); ++r) { + r->expand_recursive (); + } + } else { + for (CTree_Helpers::RowIterator r = region_list_display.rows().begin(); r != region_list_display.rows().end(); ++r) { + r->collapse (); + } + } + region_list_display.thaw (); +} + +gint +Editor::region_list_display_key_press (GdkEventKey* ev) +{ + return FALSE; +} + +gint +Editor::region_list_display_key_release (GdkEventKey* ev) +{ + switch (ev->keyval) { + case GDK_Delete: + remove_selected_regions_from_region_list (); + return TRUE; + break; + default: + break; + } + + return FALSE; + +} + +gint +Editor::region_list_display_button_press (GdkEventButton *ev) +{ + int row, col; + AudioRegion *region; + + if (Keyboard::is_delete_event (ev)) { + if (region_list_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) { + if ((region = (AudioRegion *) region_list_display.row(row).get_data()) != 0) { + delete region; + } + } + return TRUE; + } + + if (Keyboard::is_context_menu_event (ev)) { + region_list_column_click (-1); + return TRUE; + } + + switch (ev->button) { + case 1: + if (region_list_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) { + if ((region = (AudioRegion *) region_list_display.row(row).get_data()) != 0) { + + if (wave_cursor == 0) { + GdkPixmap *source, *mask; + GdkColor fg = { 0, 65535, 0, 0 }; /* Red. */ + GdkColor bg = { 0, 0, 0, 65535 }; /* Blue. */ + + source = gdk_bitmap_create_from_data (NULL, wave_cursor_bits, + wave_cursor_width, wave_cursor_height); + mask = gdk_bitmap_create_from_data (NULL, wave_cursor_mask_bits, + wave_cursor_mask_width, wave_cursor_mask_height); + + wave_cursor = gdk_cursor_new_from_pixmap (source, + mask, + &fg, + &bg, + wave_cursor_x_hot, + wave_cursor_y_hot); + gdk_pixmap_unref (source); + gdk_pixmap_unref (mask); + } + region_list_display_drag_region = region; + need_wave_cursor = 1; + + /* audition on double click */ + if (ev->type == GDK_2BUTTON_PRESS) { + consider_auditioning (region); + } + + return TRUE; + } + + } + break; + + case 2: + if (!Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + if (region_list_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) { + if ((region = (AudioRegion *) region_list_display.get_row_data (row)) != 0) { + if (consider_auditioning (region)) { + region_list_display.row(row).select(); + } + else { + region_list_display.row(row).unselect(); + } + return TRUE; + } + } + } + + /* to prevent regular selection -- i dont think this is needed JLC */ + return stop_signal (region_list_display, "button_press_event"); + break; + + case 3: + break; + default: + break; + } + + return FALSE; +} + +gint +Editor::region_list_display_button_release (GdkEventButton *ev) +{ + int row, col; + + if (region_list_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) { + region_list_button_region = (AudioRegion *) region_list_display.get_row_data (row); + } else { + region_list_button_region = 0; + } + + if (Keyboard::is_delete_event (ev)) { + remove_region_from_region_list (); + return TRUE; + } + + switch (ev->button) { + case 1: + if (region_list_display_drag_region) { + insert_region_list_drag (*region_list_display_drag_region); + } + + track_canvas_scroller.get_window().set_cursor (current_canvas_cursor); + region_list_display.get_window().set_cursor (0); + + region_list_display_drag_region = 0; + need_wave_cursor = 0; + + return TRUE; + break; + + case 3: + if (!Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + + if (region_list_menu == 0) { + build_region_list_menu (); + } + + bool sensitive; + + if (region_list_display.selection().size() != 0) { + sensitive = true; + } else { + sensitive = false; + } + + for (vector::iterator i = rl_context_menu_region_items.begin(); i != rl_context_menu_region_items.end(); ++i) { + (*i)->set_sensitive (sensitive); + } + + region_list_menu->popup (0, 0); + } + + return TRUE; + break; + default: + break; + } + return FALSE; +} + +gint +Editor::region_list_display_motion (GdkEventMotion *ev) +{ + if (need_wave_cursor == 1) { + track_canvas_scroller.get_window().set_cursor (wave_cursor); + region_list_display.get_window().set_cursor (wave_cursor); + gdk_flush (); + need_wave_cursor = 2; + } + return FALSE; +} + +void +Editor::region_list_display_selected (gint row, gint col, GdkEvent *ev) +{ + AudioRegion* region = static_cast(region_list_display.get_row_data (row)); + + if (session == 0 || region == 0) { + return; + } + + set_selected_regionview_from_region_list (*region, false); +} + +void +Editor::region_list_display_unselected (gint row, gint col, GdkEvent *ev) +{ +} + +bool +Editor::consider_auditioning (AudioRegion *r) +{ + if (r == 0) { + session->cancel_audition (); + return false; + } + + if (session->is_auditioning()) { + session->cancel_audition (); + if (r == last_audition_region) { + return false; + } + } + + session->audition_region (*r); + last_audition_region = r; + + return true; +} + +gint +Editor::region_list_display_enter_notify (GdkEventCrossing *ev) +{ + ARDOUR_UI::instance()->allow_focus (true); + region_list_display.grab_focus (); + return FALSE; +} + +gint +Editor::region_list_display_leave_notify (GdkEventCrossing *ev) +{ + ARDOUR_UI::instance()->allow_focus (false); + return FALSE; +} + +gint +Editor::_region_list_sorter (GtkCList* clist, gconstpointer a, gconstpointer b) +{ + Editor* editor = static_cast (gtk_object_get_data (GTK_OBJECT(clist), "editor")); + return editor->region_list_sorter (a, b); +} + +gint +Editor::region_list_sorter (gconstpointer a, gconstpointer b) +{ + GtkCListRow* row1 = (GtkCListRow *) a; + GtkCListRow* row2 = (GtkCListRow *) b; + + AudioRegion* region1 = static_cast (row1->data); + AudioRegion* region2 = static_cast (row2->data); + + if (region1 == 0 || region2 == 0) { + switch (region_list_sort_type) { + case ByName: + return true; /* XXX compare text in rows */ + default: + return true; + } + } + + switch (region_list_sort_type) { + case ByName: + return strcasecmp (region1->name().c_str(), region2->name().c_str()); + break; + + case ByLength: + return region1->length() - region2->length(); + break; + + case ByPosition: + return region1->position() - region2->position(); + break; + + case ByTimestamp: + return region1->source().timestamp() - region2->source().timestamp(); + break; + + case ByStartInFile: + return region1->start() - region2->start(); + break; + + case ByEndInFile: + return (region1->start() + region1->length()) - (region2->start() + region2->length()); + break; + + case BySourceFileName: + return strcasecmp (region1->source().name().c_str(), region2->source().name().c_str()); + break; + + case BySourceFileLength: + return region1->source().length() - region2->source().length(); + break; + + case BySourceFileCreationDate: + return region1->source().timestamp() - region2->source().timestamp(); + break; + + case BySourceFileFS: + if (region1->source().name() == region2->source().name()) { + return strcasecmp (region1->name().c_str(), region2->name().c_str()); + } else { + return strcasecmp (region1->source().name().c_str(), region2->source().name().c_str()); + } + break; + } + + return FALSE; +} + +void +Editor::reset_region_list_sort_type (RegionListSortType type) +{ + if (type != region_list_sort_type) { + region_list_sort_type = type; + + switch (type) { + case ByName: + region_list_display.set_column_title(0, _("Regions/name")); + break; + + case ByLength: + region_list_display.set_column_title (0, _("Regions/length")); + break; + + case ByPosition: + region_list_display.set_column_title (0, _("Regions/position")); + break; + + case ByTimestamp: + region_list_display.set_column_title (0, _("Regions/creation")); + break; + + case ByStartInFile: + region_list_display.set_column_title (0, _("Regions/start")); + break; + + case ByEndInFile: + region_list_display.set_column_title (0, _("Regions/end")); + break; + + case BySourceFileName: + region_list_display.set_column_title (0, _("Regions/file name")); + break; + + case BySourceFileLength: + region_list_display.set_column_title (0, _("Regions/file size")); + break; + + case BySourceFileCreationDate: + region_list_display.set_column_title (0, _("Regions/file date")); + break; + + case BySourceFileFS: + region_list_display.set_column_title (0, _("Regions/file system")); + break; + } + + region_list_display.sort (); + } +} + +void +Editor::reset_region_list_sort_direction (bool up) +{ + region_list_display.set_sort_type (up ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING); + region_list_display.sort (); +} + +void +Editor::audition_region_from_region_list () +{ + if (region_list_button_region) { + consider_auditioning (dynamic_cast (region_list_button_region)); + } +} + +void +Editor::hide_region_from_region_list () +{ + if (session == 0 || region_list_button_region == 0) { + return; + } + + region_list_button_region->set_hidden (true); +} + +void +Editor::remove_region_from_region_list () +{ + if (session == 0 || region_list_button_region == 0) { + return; + } + + session->remove_region_from_region_list (*region_list_button_region); +} + +void +Editor::remove_selected_regions_from_region_list () +{ + using namespace Gtk::CTree_Helpers; + SelectionList& selected = region_list_display.selection(); + + /* called from idle context to avoid snafus with the list + state. + */ + + if (selected.empty() || session == 0) { + return; + } + + vector to_be_deleted; + + for (SelectionList::iterator i = selected.begin(); i != selected.end(); ++i) { + to_be_deleted.push_back (static_cast ((*i).get_data())); + } + + for (vector::iterator i = to_be_deleted.begin(); i != to_be_deleted.end(); ++i) { + session->remove_region_from_region_list (**i); + } + + return; +} + +void +Editor::region_list_display_drag_data_received (GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *data, + guint info, + guint time) +{ + vector paths; + + if (convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) { + do_embed_sndfiles (paths, false); + } + + gtk_drag_finish (context, TRUE, FALSE, time); +} diff --git a/gtk2_ardour/editor_route_list.cc b/gtk2_ardour/editor_route_list.cc new file mode 100644 index 0000000000..e0bf98f26f --- /dev/null +++ b/gtk2_ardour/editor_route_list.cc @@ -0,0 +1,444 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include "editor.h" +#include "ardour_ui.h" +#include "audio_time_axis.h" +#include "mixer_strip.h" +#include "gui_thread.h" + +#include + +#include "i18n.h" + +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; + +void +Editor::handle_new_route_p (Route* route) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Editor::handle_new_route_p), route)); + handle_new_route (*route); +} + +void +Editor::handle_new_route (Route& route) +{ + TimeAxisView *tv; + AudioTimeAxisView *atv; + const gchar *rowdata[1]; + + if (route.hidden()) { + return; + } + + tv = new AudioTimeAxisView (*this, *session, route, track_canvas); + + track_views.push_back (tv); + + rowdata[0] = route.name ().c_str(); + + ignore_route_list_reorder = true; + route_list.rows().push_back (rowdata); + route_list.rows().back().set_data (tv); + if (tv->marked_for_display()) { + route_list.rows().back().select(); + } + + if ((atv = dynamic_cast (tv)) != 0) { + /* added a new fresh one at the end */ + if (atv->route().order_key(N_("editor")) == -1) { + atv->route().set_order_key (N_("editor"), route_list.rows().size()-1); + } + } + + ignore_route_list_reorder = false; + + route.gui_changed.connect (slot (*this, &Editor::handle_gui_changes)); + + tv->GoingAway.connect (bind (slot (*this, &Editor::remove_route), tv)); + + editor_mixer_button.set_sensitive(true); + +} + +void +Editor::handle_gui_changes (string what, void *src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Editor::handle_gui_changes), what, src)); + + if (what == "track_height") { + route_list_reordered (); + } +} + +void +Editor::remove_route (TimeAxisView *tv) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Editor::remove_route), tv)); + + TrackViewList::iterator i; + CList_Helpers::RowList::iterator ri; + + if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) { + track_views.erase (i); + } + + for (ri = route_list.rows().begin(); ri != route_list.rows().end(); ++ri) { + if (tv == ri->get_data()) { + route_list.rows().erase (ri); + break; + } + } + /* since the editor mixer goes away when you remove a route, set the + * button to inacttive + */ + editor_mixer_button.set_active(false); + + /* and disable if all tracks and/or routes are gone */ + + if (track_views.size() == 0) { + editor_mixer_button.set_sensitive(false); + } +} + +void +Editor::route_name_changed (TimeAxisView *tv) +{ + CList_Helpers::RowList::iterator i; + gint row; + + for (row = 0, i = route_list.rows().begin(); i != route_list.rows().end(); ++i, ++row) { + if (tv == i->get_data()) { + route_list.cell (row, 0).set_text (tv->name()); + break; + } + } +} + +void +Editor::route_list_selected (gint row, gint col, GdkEvent *ev) +{ + TimeAxisView *tv; + if ((tv = (TimeAxisView *) route_list.get_row_data (row)) != 0) { + tv->set_marked_for_display (true); + route_list_reordered (); + } +} + +void +Editor::route_list_unselected (gint row, gint col, GdkEvent *ev) +{ + TimeAxisView *tv; + AudioTimeAxisView *atv; + + if ((tv = (TimeAxisView *) route_list.get_row_data (row)) != 0) { + + tv->set_marked_for_display (false); + + if ((atv = dynamic_cast(tv)) != 0) { + if (current_mixer_strip && &(atv->route()) == &(current_mixer_strip->route())) { + /* this will hide the mixer strip */ + set_selected_mixer_strip(*atv); + } + } + + route_list_reordered (); + } +} + +void +Editor::unselect_strip_in_display (TimeAxisView& tv) +{ + CList_Helpers::RowIterator i; + + if ((i = route_list.rows().find_data (&tv)) != route_list.rows().end()) { + (*i).unselect (); + } +} + +void +Editor::select_strip_in_display (TimeAxisView& tv) +{ + CList_Helpers::RowIterator i; + + if ((i = route_list.rows().find_data (&tv)) != route_list.rows().end()) { + (*i).select (); + } +} + +void +Editor::queue_route_list_reordered (gint arg1, gint arg2) + +{ + /* the problem here is that we are called *before* the + list has been reordered. so just queue up + the actual re-drawer to happen once the re-ordering + is complete. + */ + + Main::idle.connect (slot (*this, &Editor::route_list_reordered)); +} + +void +Editor::redisplay_route_list () +{ + route_list_reordered (); +} + +gint +Editor::route_list_reordered () +{ + CList_Helpers::RowList::iterator i; + gdouble y; + int n; + + for (n = 0, y = 0, i = route_list.rows().begin(); i != route_list.rows().end(); ++i) { + + TimeAxisView *tv = (TimeAxisView *) (*i)->get_data (); + + AudioTimeAxisView* at; + + if (!ignore_route_list_reorder) { + + /* this reorder is caused by user action, so reassign sort order keys + to tracks. + */ + + if ((at = dynamic_cast (tv)) != 0) { + at->route().set_order_key (N_("editor"), n); + } + } + + if (tv->marked_for_display()) { + y += tv->show_at (y, n, &edit_controls_vbox); + y += track_spacing; + } else { + tv->hide (); + } + + n++; + } + + edit_controls_scroller.queue_resize (); + reset_scrolling_region (); + + //gtk_canvas_item_raise_to_top (time_line_group); + gtk_canvas_item_raise_to_top (cursor_group); + + return FALSE; +} + +void +Editor::hide_all_tracks (bool with_select) +{ + Gtk::CList_Helpers::RowList::iterator i; + Gtk::CList_Helpers::RowList& rowlist = route_list.rows(); + + route_list.freeze (); + + for (i = rowlist.begin(); i != rowlist.end(); ++i) { + TimeAxisView *tv = (TimeAxisView *) i->get_data (); + + if (with_select) { + i->unselect (); + } else { + tv->set_marked_for_display (false); + tv->hide(); + } + } + + route_list.thaw (); + + reset_scrolling_region (); +} + +void +Editor::route_list_column_click (gint col) +{ + if (route_list_menu == 0) { + build_route_list_menu (); + } + + route_list_menu->popup (0, 0); +} + +void +Editor::build_route_list_menu () +{ + using namespace Gtk::Menu_Helpers; + + route_list_menu = new Menu; + + MenuList& items = route_list_menu->items(); + route_list_menu->set_name ("ArdourContextMenu"); + + items.push_back (MenuElem (_("Show All"), slot (*this, &Editor::select_all_routes))); + items.push_back (MenuElem (_("Hide All"), slot (*this, &Editor::unselect_all_routes))); + items.push_back (MenuElem (_("Show All AbstractTracks"), slot (*this, &Editor::select_all_audiotracks))); + items.push_back (MenuElem (_("Hide All AbstractTracks"), slot (*this, &Editor::unselect_all_audiotracks))); + items.push_back (MenuElem (_("Show All AudioBus"), slot (*this, &Editor::select_all_audiobus))); + items.push_back (MenuElem (_("Hide All AudioBus"), slot (*this, &Editor::unselect_all_audiobus))); + +} + +void +Editor::unselect_all_routes () +{ + hide_all_tracks (true); +} + +void +Editor::select_all_routes () + +{ + CList_Helpers::RowList::iterator i; + + for (i = route_list.rows().begin(); i != route_list.rows().end(); ++i) { + i->select (); + } +} + +void +Editor::select_all_audiotracks () +{ + Gtk::CList_Helpers::RowList::iterator i; + Gtk::CList_Helpers::RowList& rowlist = route_list.rows(); + + route_list.freeze (); + + for (i = rowlist.begin(); i != rowlist.end(); ++i) { + TimeAxisView *tv = (TimeAxisView *) i->get_data (); + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast(tv)) != 0) { + if (atv->is_audio_track()) { + i->select (); + } + } + } + + route_list.thaw (); + +} + +void +Editor::unselect_all_audiotracks () +{ + Gtk::CList_Helpers::RowList::iterator i; + Gtk::CList_Helpers::RowList& rowlist = route_list.rows(); + + route_list.freeze (); + + for (i = rowlist.begin(); i != rowlist.end(); ++i) { + TimeAxisView *tv = (TimeAxisView *) i->get_data (); + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast(tv)) != 0) { + if (atv->is_audio_track()) { + i->unselect (); + } + } + } + + route_list.thaw (); + +} + +void +Editor::select_all_audiobus () +{ + Gtk::CList_Helpers::RowList::iterator i; + Gtk::CList_Helpers::RowList& rowlist = route_list.rows(); + + route_list.freeze (); + + for (i = rowlist.begin(); i != rowlist.end(); ++i) { + TimeAxisView *tv = (TimeAxisView *) i->get_data (); + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast(tv)) != 0) { + if (!atv->is_audio_track()) { + i->select (); + } + } + } + + route_list.thaw (); + +} + +void +Editor::unselect_all_audiobus () +{ + Gtk::CList_Helpers::RowList::iterator i; + Gtk::CList_Helpers::RowList& rowlist = route_list.rows(); + + route_list.freeze (); + + for (i = rowlist.begin(); i != rowlist.end(); ++i) { + TimeAxisView *tv = (TimeAxisView *) i->get_data (); + AudioTimeAxisView* atv; + + if ((atv = dynamic_cast(tv)) != 0) { + if (!atv->is_audio_track()) { + i->unselect (); + } + } + } + + route_list.thaw (); + +} + +gint +route_list_compare_func (GtkCList* clist, gconstpointer a, gconstpointer b) +{ + TimeAxisView *tv1; + TimeAxisView *tv2; + AudioTimeAxisView *atv1; + AudioTimeAxisView *atv2; + Route* ra; + Route* rb; + + GtkCListRow *row1 = (GtkCListRow *) a; + GtkCListRow *row2 = (GtkCListRow *) b; + + tv1 = static_cast (row1->data); + tv2 = static_cast (row2->data); + + if ((atv1 = dynamic_cast(tv1)) == 0 || + (atv2 = dynamic_cast(tv2)) == 0) { + return FALSE; + } + + ra = &atv1->route(); + rb = &atv2->route(); + + /* use of ">" forces the correct sort order */ + + return ra->order_key ("editor") > rb->order_key ("editor"); +} + diff --git a/gtk2_ardour/editor_rulers.cc b/gtk2_ardour/editor_rulers.cc new file mode 100644 index 0000000000..b8a236cb61 --- /dev/null +++ b/gtk2_ardour/editor_rulers.cc @@ -0,0 +1,1602 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include // for sprintf, grrr +#include + +#include + +#include +#include + +#include "editor.h" +#include "editing.h" +#include "gtk-custom-hruler.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; +using namespace Editing; + +Editor *Editor::ruler_editor; + +/* the order here must match the "metric" enums in editor.h */ + +GtkCustomMetric Editor::ruler_metrics[4] = { + {1, Editor::_metric_get_smpte }, + {1, Editor::_metric_get_bbt }, + {1, Editor::_metric_get_frames }, + {1, Editor::_metric_get_minsec } +}; + +void +Editor::initialize_rulers () +{ + ruler_editor = this; + ruler_grabbed_widget = 0; + + _smpte_ruler = gtk_custom_hruler_new (); + smpte_ruler = wrap (_smpte_ruler); + smpte_ruler->set_name ("SMPTERuler"); + smpte_ruler->set_usize (-1, (int)timebar_height); + gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_smpte_ruler), &ruler_metrics[ruler_metric_smpte]); + ruler_shown[ruler_metric_smpte] = true; + + _bbt_ruler = gtk_custom_hruler_new (); + bbt_ruler = wrap (_bbt_ruler); + bbt_ruler->set_name ("BBTRuler"); + bbt_ruler->set_usize (-1, (int)timebar_height); + gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_bbt_ruler), &ruler_metrics[ruler_metric_bbt]); + ruler_shown[ruler_metric_bbt] = true; + + _frames_ruler = gtk_custom_hruler_new (); + frames_ruler = wrap (_frames_ruler); + frames_ruler->set_name ("FramesRuler"); + frames_ruler->set_usize (-1, (int)timebar_height); + gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_frames_ruler), &ruler_metrics[ruler_metric_frames]); + + _minsec_ruler = gtk_custom_hruler_new (); + minsec_ruler = wrap (_minsec_ruler); + minsec_ruler->set_name ("MinSecRuler"); + minsec_ruler->set_usize (-1, (int)timebar_height); + gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_minsec_ruler), &ruler_metrics[ruler_metric_minsec]); + + ruler_shown[ruler_time_meter] = true; + ruler_shown[ruler_time_tempo] = true; + ruler_shown[ruler_time_marker] = true; + ruler_shown[ruler_time_range_marker] = true; + ruler_shown[ruler_time_transport_marker] = true; + ruler_shown[ruler_metric_frames] = false; + ruler_shown[ruler_metric_minsec] = false; + + smpte_ruler->set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + bbt_ruler->set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + frames_ruler->set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + minsec_ruler->set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + + smpte_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release)); + bbt_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release)); + frames_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release)); + minsec_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release)); + + smpte_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press)); + bbt_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press)); + frames_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press)); + minsec_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press)); + + smpte_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion)); + bbt_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion)); + frames_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion)); + minsec_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion)); + + visible_timebars = 7; /* 4 here, 3 in time_canvas */ + ruler_pressed_button = 0; +} + + +gint +Editor::ruler_button_press (GdkEventButton* ev) +{ + if (session == 0) { + return FALSE; + } + + ruler_pressed_button = ev->button; + + // jlc: grab ev->window ? + //Gtk::Main::grab_add (*minsec_ruler); + Widget * grab_widget = 0; + + if (smpte_ruler->is_realized() && ev->window == smpte_ruler->get_window()) grab_widget = smpte_ruler; + else if (bbt_ruler->is_realized() && ev->window == bbt_ruler->get_window()) grab_widget = bbt_ruler; + else if (frames_ruler->is_realized() && ev->window == frames_ruler->get_window()) grab_widget = frames_ruler; + else if (minsec_ruler->is_realized() && ev->window == minsec_ruler->get_window()) grab_widget = minsec_ruler; + + if (grab_widget) { + Gtk::Main::grab_add (*grab_widget); + ruler_grabbed_widget = grab_widget; + } + + return TRUE; +} + +gint +Editor::ruler_button_release (GdkEventButton* ev) +{ + gint x,y; + GdkModifierType state; + + /* need to use the correct x,y, the event lies */ + time_canvas_event_box.get_window().get_pointer (x, y, state); + + + ruler_pressed_button = 0; + + if (session == 0) { + return FALSE; + } + + hide_verbose_canvas_cursor(); + stop_canvas_autoscroll(); + + jack_nframes_t where = leftmost_frame + pixel_to_frame (x); + + switch (ev->button) { + case 1: + /* transport playhead */ + snap_to (where); + session->request_locate (where); + break; + + case 2: + /* edit cursor */ + if (snap_type != Editing::SnapToEditCursor) { + snap_to (where); + } + edit_cursor->set_position (where); + edit_cursor_clock.set (where); + break; + + case 3: + /* popup menu */ + snap_to (where); + popup_ruler_menu (where); + + break; + default: + break; + } + + + if (ruler_grabbed_widget) { + Gtk::Main::grab_remove (*ruler_grabbed_widget); + ruler_grabbed_widget = 0; + } + + return TRUE; +} + +gint +Editor::ruler_label_button_release (GdkEventButton* ev) +{ + if (ev->button == 3) + { + popup_ruler_menu(); + } + + return TRUE; +} + + +gint +Editor::ruler_mouse_motion (GdkEventMotion* ev) +{ + if (session == 0 || !ruler_pressed_button) { + return FALSE; + } + + double wcx=0,wcy=0; + double cx=0,cy=0; + + gint x,y; + GdkModifierType state; + + /* need to use the correct x,y, the event lies */ + time_canvas_event_box.get_window().get_pointer (x, y, state); + + + gtk_canvas_window_to_world (GTK_CANVAS(track_gtk_canvas), x, y, &wcx, &wcy); + gtk_canvas_w2c_d (GTK_CANVAS(track_gtk_canvas), wcx, wcy, &cx, &cy); + + jack_nframes_t where = leftmost_frame + pixel_to_frame (x); + + /// ripped from maybe_autoscroll + jack_nframes_t one_page = (jack_nframes_t) rint (canvas_width * frames_per_unit); + jack_nframes_t rightmost_frame = leftmost_frame + one_page; + + jack_nframes_t frame = pixel_to_frame (cx); + + if (autoscroll_timeout_tag < 0) { + if (frame > rightmost_frame) { + if (rightmost_frame < max_frames) { + start_canvas_autoscroll (1); + } + } else if (frame < leftmost_frame) { + if (leftmost_frame > 0) { + start_canvas_autoscroll (-1); + } + } + } else { + if (frame >= leftmost_frame && frame < rightmost_frame) { + stop_canvas_autoscroll (); + } + } + ////// + + snap_to (where); + + Cursor* cursor = 0; + + switch (ruler_pressed_button) { + case 1: + /* transport playhead */ + cursor = playhead_cursor; + break; + + case 2: + /* edit cursor */ + cursor = edit_cursor; + break; + + default: + break; + } + + if (cursor) + { + cursor->set_position (where); + + if (cursor == edit_cursor) { + edit_cursor_clock.set (where); + } + + show_verbose_time_cursor (where, 10, cx, 0); + } + + return TRUE; +} + + +void +Editor::popup_ruler_menu (jack_nframes_t where, ItemType t) +{ + using namespace Menu_Helpers; + + if (editor_ruler_menu == 0) { + editor_ruler_menu = new Menu; + editor_ruler_menu->set_name ("ArdourContextMenu"); + } + + // always build from scratch + MenuList& ruler_items = editor_ruler_menu->items(); + editor_ruler_menu->set_name ("ArdourContextMenu"); + ruler_items.clear(); + + CheckMenuItem * mitem; + + no_ruler_shown_update = true; + + switch (t) { + case MarkerBarItem: + ruler_items.push_back (MenuElem (_("New location marker"), bind ( slot (*this, &Editor::mouse_add_new_marker), where))); + ruler_items.push_back (MenuElem (_("Clear all locations"), slot (*this, &Editor::clear_markers))); + ruler_items.push_back (SeparatorElem ()); + break; + case RangeMarkerBarItem: + //ruler_items.push_back (MenuElem (_("New Range"))); + ruler_items.push_back (MenuElem (_("Clear all ranges"), slot (*this, &Editor::clear_ranges))); + ruler_items.push_back (SeparatorElem ()); + + break; + case TransportMarkerBarItem: + + break; + + case TempoBarItem: + ruler_items.push_back (MenuElem (_("New Tempo"), bind ( slot (*this, &Editor::mouse_add_new_tempo_event), where))); + ruler_items.push_back (MenuElem (_("Clear tempo"))); + ruler_items.push_back (SeparatorElem ()); + break; + + case MeterBarItem: + ruler_items.push_back (MenuElem (_("New Meter"), bind ( slot (*this, &Editor::mouse_add_new_meter_event), where))); + ruler_items.push_back (MenuElem (_("Clear meter"))); + ruler_items.push_back (SeparatorElem ()); + break; + + default: + break; + } + + ruler_items.push_back (CheckMenuElem (_("Min:Secs"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_metric_minsec))); + mitem = (CheckMenuItem *) ruler_items.back(); + if (ruler_shown[ruler_metric_minsec]) { + mitem->set_active(true); + } + + ruler_items.push_back (CheckMenuElem (X_("SMPTE"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_metric_smpte))); + mitem = (CheckMenuItem *) ruler_items.back(); + if (ruler_shown[ruler_metric_smpte]) { + mitem->set_active(true); + } + + ruler_items.push_back (CheckMenuElem (_("Frames"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_metric_frames))); + mitem = (CheckMenuItem *) ruler_items.back(); + if (ruler_shown[ruler_metric_frames]) { + mitem->set_active(true); + } + + ruler_items.push_back (CheckMenuElem (_("Bars:Beats"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_metric_bbt))); + mitem = (CheckMenuItem *) ruler_items.back(); + if (ruler_shown[ruler_metric_bbt]) { + mitem->set_active(true); + } + + ruler_items.push_back (SeparatorElem ()); + + ruler_items.push_back (CheckMenuElem (_("Meter"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_time_meter))); + mitem = (CheckMenuItem *) ruler_items.back(); + if (ruler_shown[ruler_time_meter]) { + mitem->set_active(true); + } + + ruler_items.push_back (CheckMenuElem (_("Tempo"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_time_tempo))); + mitem = (CheckMenuItem *) ruler_items.back(); + if (ruler_shown[ruler_time_tempo]) { + mitem->set_active(true); + } + + ruler_items.push_back (CheckMenuElem (_("Location Markers"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_time_marker))); + mitem = (CheckMenuItem *) ruler_items.back(); + if (ruler_shown[ruler_time_marker]) { + mitem->set_active(true); + } + + ruler_items.push_back (CheckMenuElem (_("Range Markers"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_time_range_marker))); + mitem = (CheckMenuItem *) ruler_items.back(); + if (ruler_shown[ruler_time_range_marker]) { + mitem->set_active(true); + } + + ruler_items.push_back (CheckMenuElem (_("Loop/Punch Ranges"), bind (slot (*this, &Editor::ruler_toggled), (int)ruler_time_transport_marker))); + mitem = (CheckMenuItem *) ruler_items.back(); + if (ruler_shown[ruler_time_transport_marker]) { + mitem->set_active(true); + } + + editor_ruler_menu->popup (1, 0); + + no_ruler_shown_update = false; +} + +void +Editor::ruler_toggled (int ruler) +{ + if (!session) return; + if (ruler < 0 || ruler >= (int) sizeof(ruler_shown)) return; + + if (no_ruler_shown_update) return; + + if (ruler_shown[ruler]) { + if (visible_timebars <= 1) { + // must always have 1 visible + return; + } + } + + ruler_shown[ruler] = !ruler_shown[ruler]; + + update_ruler_visibility (); + + // update session extra RulerVisibility + store_ruler_visibility (); +} + +void +Editor::store_ruler_visibility () +{ + XMLNode* node = new XMLNode(X_("RulerVisibility")); + + node->add_property (X_("smpte"), ruler_shown[ruler_metric_smpte] ? "yes": "no"); + node->add_property (X_("bbt"), ruler_shown[ruler_metric_bbt] ? "yes": "no"); + node->add_property (X_("frames"), ruler_shown[ruler_metric_frames] ? "yes": "no"); + node->add_property (X_("minsec"), ruler_shown[ruler_metric_minsec] ? "yes": "no"); + node->add_property (X_("tempo"), ruler_shown[ruler_time_tempo] ? "yes": "no"); + node->add_property (X_("meter"), ruler_shown[ruler_time_meter] ? "yes": "no"); + node->add_property (X_("marker"), ruler_shown[ruler_time_marker] ? "yes": "no"); + node->add_property (X_("rangemarker"), ruler_shown[ruler_time_range_marker] ? "yes": "no"); + node->add_property (X_("transportmarker"), ruler_shown[ruler_time_transport_marker] ? "yes": "no"); + + session->add_extra_xml (*node); + session->set_dirty (); +} + +void +Editor::restore_ruler_visibility () +{ + XMLProperty* prop; + XMLNode * node = session->extra_xml (X_("RulerVisibility")); + + if (node) { + if ((prop = node->property ("smpte")) != 0) { + if (prop->value() == "yes") + ruler_shown[ruler_metric_smpte] = true; + else + ruler_shown[ruler_metric_smpte] = false; + } + if ((prop = node->property ("bbt")) != 0) { + if (prop->value() == "yes") + ruler_shown[ruler_metric_bbt] = true; + else + ruler_shown[ruler_metric_bbt] = false; + } + if ((prop = node->property ("frames")) != 0) { + if (prop->value() == "yes") + ruler_shown[ruler_metric_frames] = true; + else + ruler_shown[ruler_metric_frames] = false; + } + if ((prop = node->property ("minsec")) != 0) { + if (prop->value() == "yes") + ruler_shown[ruler_metric_minsec] = true; + else + ruler_shown[ruler_metric_minsec] = false; + } + if ((prop = node->property ("tempo")) != 0) { + if (prop->value() == "yes") + ruler_shown[ruler_time_tempo] = true; + else + ruler_shown[ruler_time_tempo] = false; + } + if ((prop = node->property ("meter")) != 0) { + if (prop->value() == "yes") + ruler_shown[ruler_time_meter] = true; + else + ruler_shown[ruler_time_meter] = false; + } + if ((prop = node->property ("marker")) != 0) { + if (prop->value() == "yes") + ruler_shown[ruler_time_marker] = true; + else + ruler_shown[ruler_time_marker] = false; + } + if ((prop = node->property ("rangemarker")) != 0) { + if (prop->value() == "yes") + ruler_shown[ruler_time_range_marker] = true; + else + ruler_shown[ruler_time_range_marker] = false; + } + if ((prop = node->property ("transportmarker")) != 0) { + if (prop->value() == "yes") + ruler_shown[ruler_time_transport_marker] = true; + else + ruler_shown[ruler_time_transport_marker] = false; + } + + } + + update_ruler_visibility (); +} + + +void +Editor::update_ruler_visibility () +{ + using namespace Box_Helpers; + BoxList & lab_children = time_button_vbox.children(); + BoxList & ruler_children = time_canvas_vbox.children(); + + visible_timebars = 0; + + lab_children.clear(); + + // leave the last one (the time_canvas_scroller) intact + while (ruler_children.size() > 1) { + ruler_children.pop_front(); + } + + BoxList::iterator canvaspos = ruler_children.begin(); + + _smpte_ruler = gtk_custom_hruler_new (); + smpte_ruler = wrap (_smpte_ruler); + smpte_ruler->set_name ("SMPTERuler"); + smpte_ruler->set_usize (-1, (int)timebar_height); + gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_smpte_ruler), &ruler_metrics[ruler_metric_smpte]); + + _bbt_ruler = gtk_custom_hruler_new (); + bbt_ruler = wrap (_bbt_ruler); + bbt_ruler->set_name ("BBTRuler"); + bbt_ruler->set_usize (-1, (int)timebar_height); + gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_bbt_ruler), &ruler_metrics[ruler_metric_bbt]); + + _frames_ruler = gtk_custom_hruler_new (); + frames_ruler = wrap (_frames_ruler); + frames_ruler->set_name ("FramesRuler"); + frames_ruler->set_usize (-1, (int)timebar_height); + gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_frames_ruler), &ruler_metrics[ruler_metric_frames]); + + _minsec_ruler = gtk_custom_hruler_new (); + minsec_ruler = wrap (_minsec_ruler); + minsec_ruler->set_name ("MinSecRuler"); + minsec_ruler->set_usize (-1, (int)timebar_height); + gtk_custom_ruler_set_metric (GTK_CUSTOM_RULER(_minsec_ruler), &ruler_metrics[ruler_metric_minsec]); + + + smpte_ruler->set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + bbt_ruler->set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + frames_ruler->set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + minsec_ruler->set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + + smpte_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release)); + bbt_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release)); + frames_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release)); + minsec_ruler->button_release_event.connect (slot (*this, &Editor::ruler_button_release)); + + smpte_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press)); + bbt_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press)); + frames_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press)); + minsec_ruler->button_press_event.connect (slot (*this, &Editor::ruler_button_press)); + + smpte_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion)); + bbt_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion)); + frames_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion)); + minsec_ruler->motion_notify_event.connect (slot (*this, &Editor::ruler_mouse_motion)); + + + if (ruler_shown[ruler_metric_minsec]) { + lab_children.push_back (Element(minsec_label, false, false)); + ruler_children.insert (canvaspos, Element(*minsec_ruler, false, false)); + visible_timebars++; + } + + if (ruler_shown[ruler_metric_smpte]) { + lab_children.push_back (Element(smpte_label, false, false)); + ruler_children.insert (canvaspos, Element(*smpte_ruler, false, false)); + visible_timebars++; + } + + if (ruler_shown[ruler_metric_frames]) { + lab_children.push_back (Element(frame_label, false, false)); + ruler_children.insert (canvaspos, Element(*frames_ruler, false, false)); + visible_timebars++; + } + + if (ruler_shown[ruler_metric_bbt]) { + lab_children.push_back (Element(bbt_label, false, false)); + ruler_children.insert (canvaspos, Element(*bbt_ruler, false, false)); + visible_timebars++; + } + + double tbpos = 0.0; + double old_unit_pos ; + GtkArg args[1] ; + args[0].name = "y"; + + if (ruler_shown[ruler_time_meter]) { + lab_children.push_back (Element(meter_label, false, false)); + + gtk_object_getv (GTK_OBJECT(meter_group), 1, args) ; + old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ; + if (tbpos != old_unit_pos) { + gtk_canvas_item_move (meter_group, 0.0, tbpos - old_unit_pos) ; + } + + //gtk_canvas_item_set (meter_group, "y", tbpos, NULL); + gtk_canvas_item_show (meter_group); + tbpos += timebar_height; + visible_timebars++; + } + else { + gtk_canvas_item_hide (meter_group); + } + + if (ruler_shown[ruler_time_tempo]) { + lab_children.push_back (Element(tempo_label, false, false)); + gtk_object_getv (GTK_OBJECT(tempo_group), 1, args) ; + old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ; + if (tbpos != old_unit_pos) { + gtk_canvas_item_move (tempo_group, 0.0, tbpos - old_unit_pos) ; + } + //gtk_canvas_item_set (tempo_group, "y", tbpos, NULL); + gtk_canvas_item_show (tempo_group); + tbpos += timebar_height; + visible_timebars++; + } + else { + gtk_canvas_item_hide (tempo_group); + } + + if (ruler_shown[ruler_time_marker]) { + lab_children.push_back (Element(mark_label, false, false)); + gtk_object_getv (GTK_OBJECT(marker_group), 1, args) ; + old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ; + if (tbpos != old_unit_pos) { + gtk_canvas_item_move (marker_group, 0.0, tbpos - old_unit_pos) ; + } + //gtk_canvas_item_set (marker_group, "y", tbpos, NULL); + gtk_canvas_item_show (marker_group); + tbpos += timebar_height; + visible_timebars++; + } + else { + gtk_canvas_item_hide (marker_group); + } + + if (ruler_shown[ruler_time_range_marker]) { + lab_children.push_back (Element(range_mark_label, false, false)); + gtk_object_getv (GTK_OBJECT(range_marker_group), 1, args) ; + old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ; + if (tbpos != old_unit_pos) { + gtk_canvas_item_move (range_marker_group, 0.0, tbpos - old_unit_pos) ; + } + //gtk_canvas_item_set (marker_group, "y", tbpos, NULL); + gtk_canvas_item_show (range_marker_group); + tbpos += timebar_height; + visible_timebars++; + } + else { + gtk_canvas_item_hide (range_marker_group); + } + + if (ruler_shown[ruler_time_transport_marker]) { + lab_children.push_back (Element(transport_mark_label, false, false)); + gtk_object_getv (GTK_OBJECT(transport_marker_group), 1, args) ; + old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ; + if (tbpos != old_unit_pos) { + gtk_canvas_item_move (transport_marker_group, 0.0, tbpos - old_unit_pos) ; + } + //gtk_canvas_item_set (marker_group, "y", tbpos, NULL); + gtk_canvas_item_show (transport_marker_group); + tbpos += timebar_height; + visible_timebars++; + } + else { + gtk_canvas_item_hide (transport_marker_group); + } + + time_canvas_vbox.set_usize (-1, (int)(timebar_height * visible_timebars)); + time_canvas_event_box.queue_resize(); + + update_fixed_rulers(); + //update_tempo_based_rulers(); + tempo_map_changed(Change (0)); + + time_canvas_event_box.show_all(); + time_button_event_box.show_all(); +} + +void +Editor::update_just_smpte () +{ + ENSURE_GUI_THREAD(slot (*this, &Editor::update_just_smpte)); + + if (session == 0) { + return; + } + + /* XXX Note the potential loss of accuracy here as we convert from + an uint32_t (or larger) to a float ... what to do ? + */ + + jack_nframes_t page = (jack_nframes_t) floor (canvas_width * frames_per_unit); + jack_nframes_t rightmost_frame = leftmost_frame + page; + + if (ruler_shown[ruler_metric_smpte]) { + gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_smpte_ruler), leftmost_frame, rightmost_frame, + leftmost_frame, session->current_end_frame()); + } +} + +void +Editor::update_fixed_rulers () +{ + jack_nframes_t rightmost_frame; + + if (session == 0) { + return; + } + + /* XXX Note the potential loss of accuracy here as we convert from + an uint32_t (or larger) to a float ... what to do ? + */ + + jack_nframes_t page = (jack_nframes_t) floor (canvas_width * frames_per_unit); + + ruler_metrics[ruler_metric_smpte].units_per_pixel = frames_per_unit; + ruler_metrics[ruler_metric_frames].units_per_pixel = frames_per_unit; + ruler_metrics[ruler_metric_minsec].units_per_pixel = frames_per_unit; + + rightmost_frame = leftmost_frame + page; + + /* these force a redraw, which in turn will force execution of the metric callbacks + to compute the relevant ticks to display. + */ + + if (ruler_shown[ruler_metric_smpte]) { + gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_smpte_ruler), leftmost_frame, rightmost_frame, + leftmost_frame, session->current_end_frame()); + } + + if (ruler_shown[ruler_metric_frames]) { + gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_frames_ruler), leftmost_frame, rightmost_frame, + leftmost_frame, session->current_end_frame()); + } + + if (ruler_shown[ruler_metric_minsec]) { + gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_minsec_ruler), leftmost_frame, rightmost_frame, + leftmost_frame, session->current_end_frame()); + } +} + +void +Editor::update_tempo_based_rulers () +{ + if (session == 0) { + return; + } + + /* XXX Note the potential loss of accuracy here as we convert from + an uint32_t (or larger) to a float ... what to do ? + */ + + jack_nframes_t page = (jack_nframes_t) floor (canvas_width * frames_per_unit); + ruler_metrics[ruler_metric_bbt].units_per_pixel = frames_per_unit; + + if (ruler_shown[ruler_metric_bbt]) { + gtk_custom_ruler_set_range (GTK_CUSTOM_RULER(_bbt_ruler), leftmost_frame, leftmost_frame+page, + leftmost_frame, session->current_end_frame()); + } +} + +/* Mark generation */ + +gint +Editor::_metric_get_smpte (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars) +{ + return ruler_editor->metric_get_smpte (marks, lower, upper, maxchars); +} + +gint +Editor::_metric_get_bbt (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars) +{ + return ruler_editor->metric_get_bbt (marks, lower, upper, maxchars); +} + +gint +Editor::_metric_get_frames (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars) +{ + return ruler_editor->metric_get_frames (marks, lower, upper, maxchars); +} + +gint +Editor::_metric_get_minsec (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars) +{ + return ruler_editor->metric_get_minsec (marks, lower, upper, maxchars); +} + +gint +Editor::metric_get_smpte (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars) +{ + jack_nframes_t range; + jack_nframes_t pos; + jack_nframes_t spacer; + jack_nframes_t fr; + SMPTE_Time smpte; + gchar buf[16]; + gint nmarks = 0; + gint n; + bool show_bits = false; + bool show_frames = false; + bool show_seconds = false; + bool show_minutes = false; + bool show_hours = false; + int mark_modulo; + + if (session == 0) { + return 0; + } + + fr = session->frame_rate(); + + if (lower > (spacer = (jack_nframes_t)(128 * Editor::get_current_zoom ()))) { + lower = lower - spacer; + } else { + upper = upper + spacer - lower; + lower = 0; + } + range = upper - lower; + + if (range < (2 * session->frames_per_smpte_frame())) { /* 0 - 2 frames */ + show_bits = true; + mark_modulo = 20; + nmarks = 1 + 160; + } else if (range <= (fr / 4)) { /* 2 frames - 0.250 second */ + show_frames = true; + mark_modulo = 1; + nmarks = 1 + (range / (jack_nframes_t)session->frames_per_smpte_frame()); + } else if (range <= (fr / 2)) { /* 0.25-0.5 second */ + show_frames = true; + mark_modulo = 2; + nmarks = 1 + (range / (jack_nframes_t)session->frames_per_smpte_frame()); + } else if (range <= fr) { /* 0.5-1 second */ + show_frames = true; + mark_modulo = 5; + nmarks = 1 + (range / (jack_nframes_t)session->frames_per_smpte_frame()); + } else if (range <= 2 * fr) { /* 1-2 seconds */ + show_frames = true; + mark_modulo = 10; + nmarks = 1 + (range / (jack_nframes_t)session->frames_per_smpte_frame()); + } else if (range <= 8 * fr) { /* 2-8 seconds */ + show_seconds = true; + mark_modulo = 1; + nmarks = 1 + (range / fr); + } else if (range <= 16 * fr) { /* 8-16 seconds */ + show_seconds = true; + mark_modulo = 2; + nmarks = 1 + (range / fr); + } else if (range <= 30 * fr) { /* 16-30 seconds */ + show_seconds = true; + mark_modulo = 5; + nmarks = 1 + (range / fr); + } else if (range <= 60 * fr) { /* 30-60 seconds */ + show_seconds = true; + mark_modulo = 5; + nmarks = 1 + (range / fr); + } else if (range <= 2 * 60 * fr) { /* 1-2 minutes */ + show_seconds = true; + mark_modulo = 20; + nmarks = 1 + (range / fr); + } else if (range <= 4 * 60 * fr) { /* 2-4 minutes */ + show_seconds = true; + mark_modulo = 30; + nmarks = 1 + (range / fr); + } else if (range <= 10 * 60 * fr) { /* 4-10 minutes */ + show_minutes = true; + mark_modulo = 2; + nmarks = 1 + 10; + } else if (range <= 30 * 60 * fr) { /* 10-30 minutes */ + show_minutes = true; + mark_modulo = 5; + nmarks = 1 + 30; + } else if (range <= 60 * 60 * fr) { /* 30 minutes - 1hr */ + show_minutes = true; + mark_modulo = 10; + nmarks = 1 + 60; + } else if (range <= 4 * 60 * 60 * fr) { /* 1 - 4 hrs*/ + show_minutes = true; + mark_modulo = 30; + nmarks = 1 + (60 * 4); + } else if (range <= 8 * 60 * 60 * fr) { /* 4 - 8 hrs*/ + show_hours = true; + mark_modulo = 1; + nmarks = 1 + 8; + } else if (range <= 16 * 60 * 60 * fr) { /* 16-24 hrs*/ + show_hours = true; + mark_modulo = 1; + nmarks = 1 + 24; + } else { + + /* not possible if jack_nframes_t is a 32 bit quantity */ + + show_hours = true; + mark_modulo = 4; + nmarks = 1 + 24; + } + + pos = lower; + + *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks); + + if (show_bits) { + // Find smpte time of this sample (pos) with subframe accuracy + session->sample_to_smpte(pos, smpte, true /* use_offset */, true /* use_subframes */ ); + + for (n = 0; n < nmarks; n++) { + session->smpte_to_sample(smpte, pos, true /* use_offset */, true /* use_subframes */ ); + if ((smpte.subframes % mark_modulo) == 0) { + if (smpte.subframes == 0) { + (*marks)[n].style = GtkCustomRulerMarkMajor; + snprintf (buf, sizeof(buf), "%s%02ld:%02ld:%02ld:%02ld", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + } else { + (*marks)[n].style = GtkCustomRulerMarkMinor; + snprintf (buf, sizeof(buf), ".%02ld", smpte.subframes); + } + } else { + snprintf (buf, sizeof(buf)," "); + (*marks)[n].style = GtkCustomRulerMarkMicro; + + } + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = pos; + + // Increment subframes by one + session->smpte_increment_subframes( smpte ); + } + } else if (show_seconds) { + // Find smpte time of this sample (pos) + session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ ); + // Go to next whole second down + session->smpte_seconds_floor( smpte ); + + for (n = 0; n < nmarks; n++) { + session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ ); + if ((smpte.seconds % mark_modulo) == 0) { + if (smpte.seconds == 0) { + (*marks)[n].style = GtkCustomRulerMarkMajor; + (*marks)[n].position = pos; + } else { + (*marks)[n].style = GtkCustomRulerMarkMinor; + (*marks)[n].position = pos; + } + snprintf (buf, sizeof(buf), "%s%02ld:%02ld:%02ld:%02ld", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + } else { + snprintf (buf, sizeof(buf)," "); + (*marks)[n].style = GtkCustomRulerMarkMicro; + (*marks)[n].position = pos; + + } + (*marks)[n].label = g_strdup (buf); + session->smpte_increment_seconds( smpte ); + } + } else if (show_minutes) { + // Find smpte time of this sample (pos) + session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ ); + // Go to next whole minute down + session->smpte_minutes_floor( smpte ); + + for (n = 0; n < nmarks; n++) { + session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ ); + if ((smpte.minutes % mark_modulo) == 0) { + if (smpte.minutes == 0) { + (*marks)[n].style = GtkCustomRulerMarkMajor; + } else { + (*marks)[n].style = GtkCustomRulerMarkMinor; + } + snprintf (buf, sizeof(buf), "%s%02ld:%02ld:%02ld:%02ld", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + } else { + snprintf (buf, sizeof(buf)," "); + (*marks)[n].style = GtkCustomRulerMarkMicro; + + } + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = pos; + session->smpte_increment_minutes( smpte ); + } + } else if (show_hours) { + // Find smpte time of this sample (pos) + session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ ); + // Go to next whole hour down + session->smpte_hours_floor( smpte ); + + for (n = 0; n < nmarks; n++) { + session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ ); + if ((smpte.hours % mark_modulo) == 0) { + (*marks)[n].style = GtkCustomRulerMarkMajor; + snprintf (buf, sizeof(buf), "%s%02ld:%02ld:%02ld:%02ld", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + } else { + snprintf (buf, sizeof(buf)," "); + (*marks)[n].style = GtkCustomRulerMarkMicro; + + } + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = pos; + + session->smpte_increment_hours( smpte ); + } + } else { // show_frames + // Find smpte time of this sample (pos) + session->sample_to_smpte(pos, smpte, true /* use_offset */, false /* use_subframes */ ); + // Go to next whole frame down + session->smpte_frames_floor( smpte ); + + for (n = 0; n < nmarks; n++) { + session->smpte_to_sample(smpte, pos, true /* use_offset */, false /* use_subframes */ ); + if ((smpte.frames % mark_modulo) == 0) { + (*marks)[n].style = GtkCustomRulerMarkMajor; + (*marks)[n].position = pos; + snprintf (buf, sizeof(buf), "%s%02ld:%02ld:%02ld:%02ld", smpte.negative ? "-" : "", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + } else { + snprintf (buf, sizeof(buf)," "); + (*marks)[n].style = GtkCustomRulerMarkMicro; + (*marks)[n].position = pos; + + } + (*marks)[n].label = g_strdup (buf); + session->smpte_increment( smpte ); + } + } + + return nmarks; +} + + +gint +Editor::metric_get_bbt (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars) +{ + if (session == 0) { + return 0; + } + + TempoMap::BBTPointList::iterator i; + TempoMap::BBTPointList *zoomed_bbt_points; + uint32_t beats = 0; + uint32_t bars = 0; + uint32_t tick = 0; + uint32_t skip; + uint32_t t; + uint32_t zoomed_beats = 0; + uint32_t zoomed_bars = 0; + uint32_t desirable_marks; + uint32_t magic_accent_number = 1; + gint nmarks; + char buf[64]; + gint n; + jack_nframes_t pos; + jack_nframes_t frame_one_beats_worth; + jack_nframes_t frame_skip; + double frame_skip_error; + double accumulated_error; + bool bar_helper_on = true; + + + BBT_Time previous_beat; + BBT_Time next_beat; + jack_nframes_t next_beat_pos; + + if ((desirable_marks = maxchars / 6) == 0) { + return 0; + } + + /* align the tick marks to whatever we're snapping to... */ + + if (snap_type == SnapToAThirdBeat) { + bbt_beat_subdivision = 3; + } else if (snap_type == SnapToAQuarterBeat) { + bbt_beat_subdivision = 4; + } else if (snap_type == SnapToAEighthBeat) { + bbt_beat_subdivision = 8; + magic_accent_number = 2; + } else if (snap_type == SnapToASixteenthBeat) { + bbt_beat_subdivision = 16; + magic_accent_number = 4; + } else if (snap_type == SnapToAThirtysecondBeat) { + bbt_beat_subdivision = 32; + magic_accent_number = 8; + } else { + bbt_beat_subdivision = 4; + } + + /* First find what a beat's distance is, so we can start plotting stuff before the beginning of the ruler */ + + session->bbt_time(lower,previous_beat); + previous_beat.ticks = 0; + next_beat = previous_beat; + + if (session->tempo_map().meter_at(lower).beats_per_bar() < (next_beat.beats + 1)) { + next_beat.bars += 1; + next_beat.beats = 1; + } else { + next_beat.beats += 1; + } + + frame_one_beats_worth = session->tempo_map().frame_time(next_beat) - session->tempo_map().frame_time(previous_beat); + + + zoomed_bbt_points = session->tempo_map().get_points((lower >= frame_one_beats_worth) ? lower - frame_one_beats_worth : 0, upper); + + if (current_bbt_points == 0 || zoomed_bbt_points == 0 || zoomed_bbt_points->empty()) { + return 0; + } + + for (i = current_bbt_points->begin(); i != current_bbt_points->end(); i++) { + if ((*i).type == TempoMap::Beat) { + beats++; + } else if ((*i).type == TempoMap::Bar) { + bars++; + } + } + /*Only show the bar helper if there aren't many bars on the screen */ + if (bars > 1) { + bar_helper_on = false; + } + + for (i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end(); i++) { + if ((*i).type == TempoMap::Beat) { + zoomed_beats++; + } else if ((*i).type == TempoMap::Bar) { + zoomed_bars++; + } + } + + if (desirable_marks > (beats / 4)) { + + /* we're in beat land...*/ + + double position_of_helper; + bool i_am_accented = false; + bool we_need_ticks = false; + + position_of_helper = lower + (30 * Editor::get_current_zoom ()); + + if (desirable_marks >= (beats * 2)) { + nmarks = (zoomed_beats * bbt_beat_subdivision) + 1; + we_need_ticks = true; + } else { + nmarks = zoomed_beats + 1; + } + + *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks); + + (*marks)[0].label = g_strdup(" "); + (*marks)[0].position = lower; + (*marks)[0].style = GtkCustomRulerMarkMicro; + + for (n = 1, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; ++i) { + + if ((*i).frame <= lower && (bar_helper_on)) { + + snprintf (buf, sizeof(buf), "<%" PRIu32 "|%" PRIu32, (*i).bar, (*i).beat); + (*marks)[0].label = g_strdup (buf); + } else { + + + if ((*i).type == TempoMap::Bar) { + tick = 0; + (((*i).frame < position_of_helper) && bar_helper_on) ? + snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar); + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = (*i).frame; + (*marks)[n].style = GtkCustomRulerMarkMajor; + n++; + + } else if (((*i).type == TempoMap::Beat) && ((*i).beat > 1)) { + tick = 0; + ((((*i).frame < position_of_helper) && bar_helper_on) || !we_need_ticks) ? + snprintf (buf, sizeof(buf), " ") : snprintf (buf, sizeof(buf), "%" PRIu32, (*i).beat); + if (((*i).beat % 2 == 1) || we_need_ticks) { + (*marks)[n].style = GtkCustomRulerMarkMinor; + } else { + (*marks)[n].style = GtkCustomRulerMarkMicro; + } + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = (*i).frame; + n++; + } + + } + /* Find the next beat */ + + session->bbt_time((*i).frame, next_beat); + + if (session->tempo_map().meter_at((*i).frame).beats_per_bar() > (next_beat.beats + 1)) { + next_beat.beats += 1; + } else { + next_beat.bars += 1; + next_beat.beats = 1; + } + + next_beat_pos = session->tempo_map().frame_time(next_beat); + + /* Add the tick marks */ + + if (we_need_ticks) { + + frame_skip = (jack_nframes_t) floor ((session->frame_rate() * 60) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute())); + frame_skip_error = ((session->frame_rate() * 60.0f) / (bbt_beat_subdivision * (*i).tempo->beats_per_minute())) - frame_skip; + skip = (uint32_t) (Meter::ticks_per_beat / bbt_beat_subdivision); + + pos = (*i).frame + frame_skip; + accumulated_error = frame_skip_error; + + tick += skip; + + for (t = 0; tick < Meter::ticks_per_beat && pos <= next_beat_pos ; pos += frame_skip, tick += skip, ++t) { + + if (t % magic_accent_number == (magic_accent_number - 1)) { + i_am_accented = true; + } + if (Editor::get_current_zoom () > 32) { + snprintf (buf, sizeof(buf), " "); + } else if ((Editor::get_current_zoom () > 8) && !i_am_accented) { + snprintf (buf, sizeof(buf), " "); + } else if (bar_helper_on && (pos < position_of_helper)) { + snprintf (buf, sizeof(buf), " "); + } else { + snprintf (buf, sizeof(buf), "%" PRIu32, tick); + } + + (*marks)[n].label = g_strdup (buf); + + /* Error compensation for float to jack_nframes_t*/ + accumulated_error += frame_skip_error; + if (accumulated_error > 1) { + pos += 1; + accumulated_error -= 1.0f; + } + + (*marks)[n].position = pos; + + if ((bbt_beat_subdivision > 4) && i_am_accented) { + (*marks)[n].style = GtkCustomRulerMarkMinor; + } else { + (*marks)[n].style = GtkCustomRulerMarkMicro; + } + i_am_accented = false; + n++; + + } + } + } + delete zoomed_bbt_points; + return n; //return the actual number of marks made, since we might have skipped some fro fractional time signatures + + } else { + + /* we're in bar land */ + + if (desirable_marks < (uint32_t) (zoomed_bars / 256)) { + nmarks = 1; + *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks); + snprintf (buf, sizeof(buf), "too many bars... (currently %" PRIu32 ")", zoomed_bars ); + (*marks)[0].style = GtkCustomRulerMarkMajor; + (*marks)[0].label = g_strdup (buf); + (*marks)[0].position = lower; + } else if (desirable_marks < (uint32_t) (nmarks = (gint) (zoomed_bars / 64))) { + *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks); + for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; i++) { + if ((*i).type == TempoMap::Bar) { + if ((*i).bar % 64 == 1) { + if ((*i).bar % 256 == 1) { + snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar); + (*marks)[n].style = GtkCustomRulerMarkMajor; + } else { + snprintf (buf, sizeof(buf), " "); + if ((*i).bar % 256 == 129) { + (*marks)[n].style = GtkCustomRulerMarkMinor; + } else { + (*marks)[n].style = GtkCustomRulerMarkMicro; + } + } + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = (*i).frame; + n++; + } + } + } + } else if (desirable_marks < (uint32_t) (nmarks = (gint)(zoomed_bars / 16))) { + *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks); + for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; i++) { + if ((*i).type == TempoMap::Bar) { + if ((*i).bar % 16 == 1) { + if ((*i).bar % 64 == 1) { + snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar); + (*marks)[n].style = GtkCustomRulerMarkMajor; + } else { + snprintf (buf, sizeof(buf), " "); + if ((*i).bar % 64 == 33) { + (*marks)[n].style = GtkCustomRulerMarkMinor; + } else { + (*marks)[n].style = GtkCustomRulerMarkMicro; + } + } + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = (*i).frame; + n++; + } + } + } + } else if (desirable_marks < (uint32_t) (nmarks = (gint)(zoomed_bars / 4))){ + *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks); + for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; ++i) { + if ((*i).type == TempoMap::Bar) { + if ((*i).bar % 4 == 1) { + if ((*i).bar % 16 == 1) { + snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar); + (*marks)[n].style = GtkCustomRulerMarkMajor; + } else { + snprintf (buf, sizeof(buf), " "); + if ((*i).bar % 16 == 9) { + (*marks)[n].style = GtkCustomRulerMarkMinor; + } else { + (*marks)[n].style = GtkCustomRulerMarkMicro; + } + } + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = (*i).frame; + n++; + } + } + } + } else { + nmarks = zoomed_bars; + *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks); + for (n = 0, i = zoomed_bbt_points->begin(); i != zoomed_bbt_points->end() && n < nmarks; i++) { + if ((*i).type == TempoMap::Bar) { + if ((*i).bar % 4 == 1) { + snprintf (buf, sizeof(buf), "%" PRIu32, (*i).bar); + (*marks)[n].style = GtkCustomRulerMarkMajor; + } else { + snprintf (buf, sizeof(buf), " "); + if ((*i).bar % 4 == 3) { + (*marks)[n].style = GtkCustomRulerMarkMinor; + } else { + (*marks)[n].style = GtkCustomRulerMarkMicro; + } + } + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = (*i).frame; + n++; + } + } + } + delete zoomed_bbt_points; + return nmarks; + } +} + +gint +Editor::metric_get_frames (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars) +{ + jack_nframes_t mark_interval; + jack_nframes_t pos; + gchar buf[16]; + gint nmarks; + gint n; + + if (session == 0) { + return 0; + } + + mark_interval = (upper - lower) / 5; + if (mark_interval > session->frame_rate()) { + mark_interval -= mark_interval % session->frame_rate(); + } else { + mark_interval = session->frame_rate() / (session->frame_rate() / mark_interval ) ; + } + nmarks = 5; + *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks); + for (n = 0, pos = lower; n < nmarks; pos += mark_interval, ++n) { + snprintf (buf, sizeof(buf), "%u", pos); + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = pos; + (*marks)[n].style = GtkCustomRulerMarkMajor; + } + + return nmarks; +} + +static void +sample_to_clock_parts ( jack_nframes_t sample, + jack_nframes_t sample_rate, + long *hrs_p, + long *mins_p, + long *secs_p, + long *millisecs_p) + +{ + jack_nframes_t left; + long hrs; + long mins; + long secs; + long millisecs; + + left = sample; + hrs = left / (sample_rate * 60 * 60); + left -= hrs * sample_rate * 60 * 60; + mins = left / (sample_rate * 60); + left -= mins * sample_rate * 60; + secs = left / sample_rate; + left -= secs * sample_rate; + millisecs = left * 1000 / sample_rate; + + *millisecs_p = millisecs; + *secs_p = secs; + *mins_p = mins; + *hrs_p = hrs; + + return; +} + +gint +Editor::metric_get_minsec (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars) +{ + jack_nframes_t range; + jack_nframes_t fr; + jack_nframes_t mark_interval; + jack_nframes_t pos; + jack_nframes_t spacer; + long hrs, mins, secs, millisecs; + gchar buf[16]; + gint nmarks; + gint n; + gint mark_modulo = 100; + bool show_seconds = false; + bool show_minutes = false; + bool show_hours = false; + + if (session == 0) { + return 0; + } + + fr = session->frame_rate(); + + /* to prevent 'flashing' */ + if (lower > (spacer = (jack_nframes_t)(128 * Editor::get_current_zoom ()))) { + lower = lower - spacer; + } else { + upper = upper + spacer; + lower = 0; + } + range = upper - lower; + + if (range < (fr / 50)) { + mark_interval = fr / 100; /* show 1/100 seconds */ + mark_modulo = 10; + } else if (range <= (fr / 10)) { /* 0-0.1 second */ + mark_interval = fr / 50; /* show 1/50 seconds */ + mark_modulo = 20; + } else if (range <= (fr / 2)) { /* 0-0.5 second */ + mark_interval = fr / 20; /* show 1/20 seconds */ + mark_modulo = 100; + } else if (range <= fr) { /* 0-1 second */ + mark_interval = fr / 10; /* show 1/10 seconds */ + mark_modulo = 200; + } else if (range <= 2 * fr) { /* 1-2 seconds */ + mark_interval = fr / 2; /* show 1/2 seconds */ + mark_modulo = 500; + } else if (range <= 8 * fr) { /* 2-5 seconds */ + mark_interval = fr / 5; /* show 2 seconds */ + mark_modulo = 1000; + } else if (range <= 16 * fr) { /* 8-16 seconds */ + mark_interval = fr; /* show 1 seconds */ + show_seconds = true; + mark_modulo = 5; + } else if (range <= 30 * fr) { /* 10-30 seconds */ + mark_interval = fr; /* show 10 seconds */ + show_seconds = true; + mark_modulo = 5; + } else if (range <= 60 * fr) { /* 30-60 seconds */ + mark_interval = 5 * fr; /* show 5 seconds */ + show_seconds = true; + mark_modulo = 3; + } else if (range <= 2 * 60 * fr) { /* 1-2 minutes */ + mark_interval = 5 * fr; /* show 5 seconds */ + show_seconds = true; + mark_modulo = 3; + } else if (range <= 4 * 60 * fr) { /* 4 minutes */ + mark_interval = 10 * fr; /* show 10 seconds */ + show_seconds = true; + mark_modulo = 30; + } else if (range <= 10 * 60 * fr) { /* 10 minutes */ + mark_interval = 30 * fr; /* show 30 seconds */ + show_seconds = true; + mark_modulo = 60; + } else if (range <= 30 * 60 * fr) { /* 10-30 minutes */ + mark_interval = 60 * fr; /* show 1 minute */ + show_minutes = true; + mark_modulo = 5; + } else if (range <= 60 * 60 * fr) { /* 30 minutes - 1hr */ + mark_interval = 2 * 60 * fr; /* show 2 minutes */ + show_minutes = true; + mark_modulo = 10; + } else if (range <= 4 * 60 * 60 * fr) { /* 1 - 4 hrs*/ + mark_interval = 5 * 60 * fr; /* show 10 minutes */ + show_minutes = true; + mark_modulo = 30; + } else if (range <= 8 * 60 * 60 * fr) { /* 4 - 8 hrs*/ + mark_interval = 20 * 60 * fr; /* show 20 minutes */ + show_minutes = true; + mark_modulo = 60; + } else if (range <= 16 * 60 * 60 * fr) { /* 16-24 hrs*/ + mark_interval = 60 * 60 * fr; /* show 60 minutes */ + show_hours = true; + mark_modulo = 2; + } else { + + /* not possible if jack_nframes_t is a 32 bit quantity */ + + mark_interval = 4 * 60 * 60 * fr; /* show 4 hrs */ + } + + nmarks = 1 + (range / mark_interval); + *marks = (GtkCustomRulerMark *) g_malloc (sizeof(GtkCustomRulerMark) * nmarks); + pos = ((lower + (mark_interval/2))/mark_interval) * mark_interval; + + if (show_seconds) { + for (n = 0; n < nmarks; pos += mark_interval, ++n) { + sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs); + if (secs % mark_modulo == 0) { + if (secs == 0) { + (*marks)[n].style = GtkCustomRulerMarkMajor; + } else { + (*marks)[n].style = GtkCustomRulerMarkMinor; + } + snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs); + } else { + snprintf (buf, sizeof(buf), " "); + (*marks)[n].style = GtkCustomRulerMarkMicro; + } + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = pos; + } + } else if (show_minutes) { + for (n = 0; n < nmarks; pos += mark_interval, ++n) { + sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs); + if (mins % mark_modulo == 0) { + if (mins == 0) { + (*marks)[n].style = GtkCustomRulerMarkMajor; + } else { + (*marks)[n].style = GtkCustomRulerMarkMinor; + } + snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs); + } else { + snprintf (buf, sizeof(buf), " "); + (*marks)[n].style = GtkCustomRulerMarkMicro; + } + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = pos; + } + } else if (show_hours) { + for (n = 0; n < nmarks; pos += mark_interval, ++n) { + sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs); + if (hrs % mark_modulo == 0) { + (*marks)[n].style = GtkCustomRulerMarkMajor; + snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs); + } else { + snprintf (buf, sizeof(buf), " "); + (*marks)[n].style = GtkCustomRulerMarkMicro; + } + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = pos; + } + } else { + for (n = 0; n < nmarks; pos += mark_interval, ++n) { + sample_to_clock_parts (pos, fr, &hrs, &mins, &secs, &millisecs); + if (millisecs % mark_modulo == 0) { + if (millisecs == 0) { + (*marks)[n].style = GtkCustomRulerMarkMajor; + } else { + (*marks)[n].style = GtkCustomRulerMarkMinor; + } + snprintf (buf, sizeof(buf), "%02ld:%02ld:%02ld.%03ld", hrs, mins, secs, millisecs); + } else { + snprintf (buf, sizeof(buf), " "); + (*marks)[n].style = GtkCustomRulerMarkMicro; + } + (*marks)[n].label = g_strdup (buf); + (*marks)[n].position = pos; + } + } + + return nmarks; +} diff --git a/gtk2_ardour/editor_scrub.cc b/gtk2_ardour/editor_scrub.cc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/gtk2_ardour/editor_selection_list.cc b/gtk2_ardour/editor_selection_list.cc new file mode 100644 index 0000000000..36d9e858f6 --- /dev/null +++ b/gtk2_ardour/editor_selection_list.cc @@ -0,0 +1,185 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#include "editor.h" +#include "selection.h" +#include "time_axis_view.h" +#include "ardour_ui.h" +#include "prompter.h" + +#include "i18n.h" + +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; +using namespace Gtkmmext; + +void +Editor::handle_new_named_selection () +{ + ARDOUR_UI::instance()->call_slot (slot (*this, &Editor::redisplay_named_selections)); +} + +void +Editor::add_named_selection_to_named_selection_display (NamedSelection& selection) +{ + const gchar *row[1]; + + row[0] = selection.name.c_str(); + named_selection_display.rows().push_back (row); + named_selection_display.rows().back().set_data (&selection); +} + +void +Editor::redisplay_named_selections () +{ + named_selection_display.freeze (); + named_selection_display.clear (); + session->foreach_named_selection (*this, &Editor::add_named_selection_to_named_selection_display); + named_selection_display.thaw (); +} + +gint +Editor::named_selection_display_button_press (GdkEventButton *ev) +{ + NamedSelection* named_selection; + gint row; + gint col; + + switch (ev->button) { + case 1: + if (Keyboard::is_delete_event (ev)) { + if (named_selection_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) { + if ((named_selection = reinterpret_cast (named_selection_display.get_row_data (row))) != 0) { + session->remove_named_selection (named_selection); + return stop_signal (named_selection_display, "button_press_event"); + } + } + } + break; + + case 2: + break; + + case 3: + break; + default: + break; + } + return FALSE; +} + + +void +Editor::named_selection_display_selected (gint row, gint col, GdkEvent *ev) +{ +} + +void +Editor::named_selection_display_unselected (gint row, gint col, GdkEvent *ev) +{ +} + +void +Editor::name_selection () +{ + ArdourPrompter p; + + p.set_prompt (_("name for chunk:")); + p.done.connect (slot (*this, &Editor::named_selection_name_chosen)); + p.change_labels (_("Create chunk"), _("Forget it")); + p.show_all (); + + Gtk::Main::run (); + + if (p.status == Prompter::entered) { + string name; + p.get_result (name); + + if (name.length()){ + create_named_selection (name); + } + } +} + +void +Editor::named_selection_name_chosen () +{ + Gtk::Main::quit (); +} + +void +Editor::create_named_selection (string name) +{ + if (session == 0) { + return; + } + + /* check for a range-based selection */ + + if (selection->time.empty()) { + return; + } + + + TrackViewList *views = get_valid_views (selection->time.track, selection->time.group); + + if (views->empty()) { + delete views; + return; + } + + Playlist* what_we_found; + list thelist; + + for (TrackViewList::iterator i = views->begin(); i != views->end(); ++i) { + + Playlist *pl = (*i)->playlist(); + + if (pl) { + + if ((what_we_found = pl->copy (selection->time, false)) != 0) { + + thelist.push_back (what_we_found); + } + } + } + + NamedSelection* ns; + + ns = new NamedSelection (name, thelist); + + /* make the one we just added be selected */ + + named_selection_display.rows().back().select (); +} + diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc new file mode 100644 index 0000000000..2f2dac1ae7 --- /dev/null +++ b/gtk2_ardour/editor_tempodisplay.cc @@ -0,0 +1,493 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include // for sprintf, grrr +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include +#include +#include + +#include "editor.h" +#include "marker.h" +#include "canvas-simpleline.h" +#include "tempo_dialog.h" +#include "rgb_macros.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace std; +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; +using namespace Editing; + +void +Editor::remove_metric_marks () +{ + /* don't delete these while handling events, just punt till the GUI is idle */ + + for (Marks::iterator x = metric_marks.begin(); x != metric_marks.end(); ++x) { + delete_when_idle (*x); + } + metric_marks.clear (); +} + +void +Editor::draw_metric_marks (const Metrics& metrics) +{ + for (Metrics::const_iterator i = metrics.begin(); i != metrics.end(); ++i) { + const MeterSection *ms; + const TempoSection *ts; + char buf[64]; + + if ((ms = dynamic_cast(*i)) != 0) { + snprintf (buf, sizeof(buf), "%g/%g", ms->beats_per_bar(), ms->note_divisor ()); + metric_marks.push_back (new MeterMarker (*this, GTK_CANVAS_GROUP(meter_group), color_map[cMeterMarker], buf, + *(const_cast(ms)), PublicEditor::canvas_meter_marker_event)); + } else if ((ts = dynamic_cast(*i)) != 0) { + snprintf (buf, sizeof (buf), "%.2f", ts->beats_per_minute()); + metric_marks.push_back (new TempoMarker (*this, GTK_CANVAS_GROUP(tempo_group), color_map[cTempoMarker], buf, + *(const_cast(ts)), PublicEditor::canvas_tempo_marker_event)); + } + + } +} + +void +Editor::tempo_map_changed (Change ignored) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Editor::tempo_map_changed), ignored)); + + if (current_bbt_points) { + delete current_bbt_points; + current_bbt_points = 0; + } + + if (session) { + current_bbt_points = session->tempo_map().get_points (leftmost_frame, leftmost_frame + current_page_frames()); + } else { + current_bbt_points = 0; + } + + redisplay_tempo (); +} + +void +Editor::redisplay_tempo () +{ + update_tempo_based_rulers (); + + remove_metric_marks (); + hide_measures (); + + if (session && current_bbt_points) { + session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks); + draw_measures (); + } + +} + +void +Editor::hide_measures () +{ + for (TimeLineList::iterator i = used_measure_lines.begin(); i != used_measure_lines.end(); ++i) { + gtk_canvas_item_hide (*i); + free_measure_lines.push_back (*i); + } + used_measure_lines.clear (); +} + +GtkCanvasItem * +Editor::get_time_line () +{ + GtkCanvasItem *line; + + if (free_measure_lines.empty()) { + line = gtk_canvas_item_new (GTK_CANVAS_GROUP(time_line_group), + gtk_canvas_simpleline_get_type(), + NULL); + // cerr << "measure line @ " << line << endl; + used_measure_lines.push_back (line); + } else { + line = free_measure_lines.front(); + free_measure_lines.erase (free_measure_lines.begin()); + used_measure_lines.push_back (line); + } + + return line; +} + +void +Editor::draw_measures () +{ + if (session == 0 || _show_measures == false) { + return; + } + + TempoMap::BBTPointList::iterator i; + TempoMap::BBTPointList *all_bbt_points; + GtkCanvasItem *line; + gdouble xpos, last_xpos; + uint32_t cnt; + uint32_t color; + + if (current_bbt_points == 0 || current_bbt_points->empty()) { + return; + } + + all_bbt_points = session->tempo_map().get_points (leftmost_frame, leftmost_frame + current_page_frames()); + + cnt = 0; + last_xpos = 0; + + /* get the first bar spacing */ + + gdouble last_beat = DBL_MAX; + gdouble beat_spacing = 0; + + for (i = all_bbt_points->begin(); i != all_bbt_points->end() && beat_spacing == 0; ++i) { + TempoMap::BBTPoint& p = (*i); + + switch (p.type) { + case TempoMap::Bar: + break; + + case TempoMap::Beat: + xpos = p.frame / (gdouble) frames_per_unit; + if (last_beat < xpos) { + beat_spacing = xpos - last_beat; + } + last_beat = xpos; + } + } + + for (i = all_bbt_points->begin(); i != all_bbt_points->end(); ++i) { + + TempoMap::BBTPoint& p = (*i); + + switch (p.type) { + case TempoMap::Bar: + break; + + case TempoMap::Beat: + xpos = p.frame / (gdouble) frames_per_unit; + + if (p.beat == 1) { + color = color_map[cMeasureLineBeat]; + } else { + color = color_map[cMeasureLineBar]; + + /* only draw beat lines if the gaps between beats + are large. + */ + + if (beat_spacing < 25.0) { + break; + } + } + + if (cnt == 0 || xpos - last_xpos > 4.0) { + line = get_time_line (); + gtk_object_set (GTK_OBJECT(line), + "x1", xpos, + "x2", xpos, + "y2", (gdouble) canvas_height, + "color_rgba", color, + NULL); + gtk_canvas_item_raise_to_top (line); + gtk_canvas_item_show (line); + last_xpos = xpos; + ++cnt; + } + break; + } + } + + delete all_bbt_points; + + /* the cursors are always on top of everything */ + + gtk_canvas_item_raise_to_top (cursor_group); + gtk_canvas_item_lower_to_bottom (time_line_group); +} + +void +Editor::mouse_add_new_tempo_event (jack_nframes_t frame) +{ + if (session == 0) { + return; + } + + + TempoMap& map(session->tempo_map()); + TempoDialog tempo_dialog (map, frame, _("add")); + + tempo_dialog.bpm_entry.activate.connect (bind (slot (tempo_dialog, &ArdourDialog::stop), 0)); + tempo_dialog.ok_button.clicked.connect (bind (slot (tempo_dialog, &ArdourDialog::stop), 0)); + tempo_dialog.cancel_button.clicked.connect (bind (slot (tempo_dialog, &ArdourDialog::stop), -1)); + + tempo_dialog.set_position (GTK_WIN_POS_MOUSE); + tempo_dialog.realize (); + tempo_dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + + ensure_float (tempo_dialog); + + tempo_dialog.run(); + + if (tempo_dialog.run_status() == 0) { + + double bpm = 0; + BBT_Time requested; + + bpm = tempo_dialog.get_bpm (); + bpm = max (0.01, bpm); + + tempo_dialog.get_bbt_time (requested); + + begin_reversible_command (_("add tempo mark")); + session->add_undo (map.get_memento()); + map.add_tempo (Tempo (bpm), requested); + session->add_redo_no_execute (map.get_memento()); + commit_reversible_command (); + + map.dump (cerr); + } +} + +void +Editor::mouse_add_new_meter_event (jack_nframes_t frame) +{ + if (session == 0) { + return; + } + + + TempoMap& map(session->tempo_map()); + MeterDialog meter_dialog (map, frame, _("add")); + + meter_dialog.ok_button.clicked.connect (bind (slot (meter_dialog, &ArdourDialog::stop), 0)); + meter_dialog.cancel_button.clicked.connect (bind (slot (meter_dialog, &ArdourDialog::stop), -1)); + + meter_dialog.set_position (GTK_WIN_POS_MOUSE); + meter_dialog.realize (); + meter_dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + + ensure_float (meter_dialog); + + meter_dialog.run (); + + if (meter_dialog.run_status() == 0) { + + double bpb = meter_dialog.get_bpb (); + bpb = max (1.0, bpb); // XXX is this a reasonable limit? + + double note_type = meter_dialog.get_note_type (); + BBT_Time requested; + + meter_dialog.get_bbt_time (requested); + + begin_reversible_command (_("add meter mark")); + session->add_undo (map.get_memento()); + map.add_meter (Meter (bpb, note_type), requested); + session->add_redo_no_execute (map.get_memento()); + commit_reversible_command (); + + map.dump (cerr); + } +} + +void +Editor::remove_tempo_marker (GtkCanvasItem* item) +{ + Marker* marker; + TempoMarker* tempo_marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + if ((tempo_marker = dynamic_cast (marker)) == 0) { + fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg; + /*NOTREACHED*/ + } + + if (tempo_marker->tempo().movable()) { + Gtk::Main::idle.connect (bind (slot (*this, &Editor::real_remove_tempo_marker), &tempo_marker->tempo())); + } +} + +void +Editor::edit_meter_section (MeterSection* section) +{ + MeterDialog meter_dialog (*section, _("done")); + + meter_dialog.ok_button.clicked.connect (bind (slot (meter_dialog, &ArdourDialog::stop), 0)); + meter_dialog.cancel_button.clicked.connect (bind (slot (meter_dialog, &ArdourDialog::stop), -1)); + + meter_dialog.set_position (GTK_WIN_POS_MOUSE); + meter_dialog.realize (); + meter_dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + + ensure_float (meter_dialog); + + meter_dialog.run (); + + if (meter_dialog.run_status() == 0) { + + double bpb = meter_dialog.get_bpb (); + bpb = max (1.0, bpb); // XXX is this a reasonable limit? + + double note_type = meter_dialog.get_note_type (); + + begin_reversible_command (_("replace tempo mark")); + session->add_undo (session->tempo_map().get_memento()); + session->tempo_map().replace_meter (*section, Meter (bpb, note_type)); + session->add_redo_no_execute (session->tempo_map().get_memento()); + commit_reversible_command (); + } +} + +void +Editor::edit_tempo_section (TempoSection* section) +{ + TempoDialog tempo_dialog (*section, _("done")); + + tempo_dialog.bpm_entry.activate.connect (bind (slot (tempo_dialog, &ArdourDialog::stop), 0)); + tempo_dialog.ok_button.clicked.connect (bind (slot (tempo_dialog, &ArdourDialog::stop), 0)); + tempo_dialog.cancel_button.clicked.connect (bind (slot (tempo_dialog, &ArdourDialog::stop), -1)); + + tempo_dialog.set_position (GTK_WIN_POS_MOUSE); + tempo_dialog.realize (); + tempo_dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + + ensure_float (tempo_dialog); + + tempo_dialog.run (); + + if (tempo_dialog.run_status() == 0) { + + double bpm = tempo_dialog.get_bpm (); + BBT_Time when; + tempo_dialog.get_bbt_time(when); + bpm = max (0.01, bpm); + + begin_reversible_command (_("replace tempo mark")); + session->add_undo (session->tempo_map().get_memento()); + session->tempo_map().replace_tempo (*section, Tempo (bpm)); + session->tempo_map().move_tempo (*section, when); + session->add_redo_no_execute (session->tempo_map().get_memento()); + commit_reversible_command (); + } +} + +void +Editor::edit_tempo_marker (GtkCanvasItem *item) +{ + Marker* marker; + TempoMarker* tempo_marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + if ((tempo_marker = dynamic_cast (marker)) == 0) { + fatal << _("programming error: marker for tempo is not a tempo marker!") << endmsg; + /*NOTREACHED*/ + } + + edit_tempo_section (&tempo_marker->tempo()); +} + +void +Editor::edit_meter_marker (GtkCanvasItem *item) +{ + Marker* marker; + MeterMarker* meter_marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + fatal << _("programming error: tempo marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + if ((meter_marker = dynamic_cast (marker)) == 0) { + fatal << _("programming error: marker for meter is not a meter marker!") << endmsg; + /*NOTREACHED*/ + } + + edit_meter_section (&meter_marker->meter()); +} + +gint +Editor::real_remove_tempo_marker (TempoSection *section) +{ + begin_reversible_command (_("remove tempo mark")); + session->add_undo (session->tempo_map().get_memento()); + session->tempo_map().remove_tempo (*section); + session->add_redo_no_execute (session->tempo_map().get_memento()); + commit_reversible_command (); + + return FALSE; +} + +void +Editor::remove_meter_marker (GtkCanvasItem* item) +{ + Marker* marker; + MeterMarker* meter_marker; + + if ((marker = reinterpret_cast (gtk_object_get_data (GTK_OBJECT(item), "marker"))) == 0) { + fatal << _("programming error: meter marker canvas item has no marker object pointer!") << endmsg; + /*NOTREACHED*/ + } + + if ((meter_marker = dynamic_cast (marker)) == 0) { + fatal << _("programming error: marker for meter is not a meter marker!") << endmsg; + /*NOTREACHED*/ + } + + if (meter_marker->meter().movable()) { + Gtk::Main::idle.connect (bind (slot (*this, &Editor::real_remove_meter_marker), &meter_marker->meter())); + } +} + +gint +Editor::real_remove_meter_marker (MeterSection *section) +{ + begin_reversible_command (_("remove tempo mark")); + session->add_undo (session->tempo_map().get_memento()); + session->tempo_map().remove_meter (*section); + session->add_redo_no_execute (session->tempo_map().get_memento()); + commit_reversible_command (); + return FALSE; +} diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc new file mode 100644 index 0000000000..70cac67d03 --- /dev/null +++ b/gtk2_ardour/editor_timefx.cc @@ -0,0 +1,239 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include + +#include +#include + +#include "editor.h" +#include "audio_time_axis.h" +#include "regionview.h" +#include "region_selection.h" + +#include +#include +#include +#include +#include +#include + +#include "i18n.h" + +using namespace ARDOUR; +using namespace SigC; +using namespace Gtk; + +Editor::TimeStretchDialog::TimeStretchDialog (Editor& e) + : ArdourDialog ("time stretch dialog"), + editor (e), + quick_button (_("Quick but Ugly")), + antialias_button (_("Skip Anti-aliasing")), + cancel_button (_("Cancel")), + action_button (_("Stretch/Shrink it")) +{ + set_modal (true); + set_position (GTK_WIN_POS_MOUSE); + set_title (_("ardour: timestretch")); + set_name (N_("TimeStretchDialog")); + + set_hide_on_stop (false); + + add (packer); + + packer.set_spacing (5); + packer.set_border_width (5); + packer.pack_start (upper_button_box); + packer.pack_start (progress_bar); + packer.pack_start (lower_button_box); + + upper_button_box.set_homogeneous (true); + upper_button_box.set_spacing (5); + upper_button_box.set_border_width (5); + upper_button_box.pack_start (quick_button, true, true); + upper_button_box.pack_start (antialias_button, true, true); + + lower_button_box.set_homogeneous (true); + lower_button_box.set_spacing (5); + lower_button_box.set_border_width (5); + lower_button_box.pack_start (action_button, true, true); + lower_button_box.pack_start (cancel_button, true, true); + + action_button.set_name (N_("TimeStretchButton")); + cancel_button.set_name (N_("TimeStretchButton")); + quick_button.set_name (N_("TimeStretchButton")); + antialias_button.set_name (N_("TimeStretchButton")); + progress_bar.set_name (N_("TimeStretchProgress")); + + action_button.clicked.connect (bind (slot (*this, &ArdourDialog::stop), 1)); +} + +gint +Editor::TimeStretchDialog::update_progress () +{ + progress_bar.set_percentage (request.progress); + return request.running; +} + +void +Editor::TimeStretchDialog::cancel_timestretch_in_progress () +{ + status = -2; + request.running = false; +} + +gint +Editor::TimeStretchDialog::delete_timestretch_in_progress (GdkEventAny* ev) +{ + status = -2; + request.running = false; + return TRUE; +} + +int +Editor::run_timestretch (AudioRegionSelection& regions, float fraction) +{ + pthread_t thread; + + if (current_timestretch == 0) { + current_timestretch = new TimeStretchDialog (*this); + } + + current_timestretch->progress_bar.set_percentage (0.0f); + current_timestretch->first_cancel = current_timestretch->cancel_button.clicked.connect (bind (slot (*current_timestretch, &ArdourDialog::stop), -1)); + current_timestretch->first_delete = current_timestretch->delete_event.connect (slot (*current_timestretch, &ArdourDialog::wm_close_event)); + + current_timestretch->run (); + + if (current_timestretch->run_status() != 1) { + current_timestretch->close (); + return 1; /* no error, but we did nothing */ + } + + current_timestretch->status = 0; + current_timestretch->regions = regions; + current_timestretch->request.fraction = fraction; + current_timestretch->request.quick_seek = current_timestretch->quick_button.get_active(); + current_timestretch->request.antialias = !current_timestretch->antialias_button.get_active(); + current_timestretch->request.progress = 0.0f; + current_timestretch->request.running = true; + + /* re-connect the cancel button and delete events */ + + current_timestretch->first_cancel.disconnect(); + current_timestretch->first_delete.disconnect(); + + current_timestretch->cancel_button.clicked.connect (slot (current_timestretch, &TimeStretchDialog::cancel_timestretch_in_progress)); + current_timestretch->delete_event.connect (slot (current_timestretch, &TimeStretchDialog::delete_timestretch_in_progress)); + + if (pthread_create_and_store ("timestretch", &thread, 0, timestretch_thread, current_timestretch)) { + current_timestretch->close (); + error << _("timestretch cannot be started - thread creation error") << endmsg; + return -1; + } + + pthread_detach (thread); + + SigC::Connection c = Main::timeout.connect (slot (current_timestretch, &TimeStretchDialog::update_progress), 100); + + while (current_timestretch->request.running) { + gtk_main_iteration (); + } + + c.disconnect (); + + current_timestretch->close (); + return current_timestretch->status; +} + +void +Editor::do_timestretch (TimeStretchDialog& dialog) +{ + AudioTrack* at; + Playlist* playlist; + AudioRegion* new_region; + + for (AudioRegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) { + + AudioRegion& aregion ((*i)->region); + TimeAxisView* tv = &(*i)->get_time_axis_view(); + AudioTimeAxisView* atv; + AudioRegionSelection::iterator tmp; + + tmp = i; + ++tmp; + + if ((atv = dynamic_cast (tv)) == 0) { + i = tmp; + continue; + } + + if ((at = dynamic_cast (&atv->route())) == 0) { + i = tmp; + continue; + } + + if ((playlist = at->disk_stream().playlist()) == 0) { + i = tmp; + continue; + } + + dialog.request.region = &aregion; + + if (!dialog.request.running) { + /* we were cancelled */ + dialog.status = 1; + return; + } + + if ((new_region = session->tempoize_region (dialog.request)) == 0) { + dialog.status = -1; + dialog.request.running = false; + return; + } + + session->add_undo (playlist->get_memento()); + playlist->replace_region (aregion, *new_region, aregion.position()); + session->add_redo_no_execute (playlist->get_memento()); + + i = tmp; + } + + dialog.status = 0; + dialog.request.running = false; +} + +void* +Editor::timestretch_thread (void *arg) +{ + PBD::ThreadCreated (pthread_self(), X_("TimeFX")); + + TimeStretchDialog* tsd = static_cast(arg); + + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); + + tsd->editor.do_timestretch (*tsd); + + return 0; +} + diff --git a/gtk2_ardour/editor_xpms b/gtk2_ardour/editor_xpms new file mode 100644 index 0000000000..880ac9ab6f --- /dev/null +++ b/gtk2_ardour/editor_xpms @@ -0,0 +1,195 @@ +/* Created with The GIMP */ +#define hand_width 16 +#define hand_height 16 +#define hand_x_hot 3 +#define hand_y_hot 0 +static const gchar hand_bits[] = { + 0x18, 0x00, 0x24, 0x00, 0x24, 0x00, 0x24, 0x00, 0xe4, 0x36, 0x24, 0x49, + 0x27, 0x49, 0x25, 0x49, 0x25, 0x49, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, + 0x02, 0x40, 0x04, 0x60, 0xfc, 0x3f, 0xfc, 0x3f }; + +/* Created with The GIMP */ +#define handmask_width 16 +#define handmask_height 16 +static const gchar handmask_bits[] = { + 0x18, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0xfc, 0x36, 0xfc, 0x7f, + 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, + 0xfe, 0x7f, 0xfc, 0x7f, 0xfc, 0x3f, 0xfc, 0x3f }; + +#define mag_width 16 +#define mag_height 16 +#define mag_x_hot 9 +#define mag_y_hot 5 +static const gchar mag_bits[] = { + 0x7f, 0xe0, 0x3f, 0xc0, 0x1f, 0x8f, 0x8f, 0x9f, 0xcf, 0x3f, 0xcf, 0x3f, + 0xcf, 0x3f, 0xcf, 0x3f, 0x8f, 0x1f, 0x1f, 0x8f, 0x0f, 0xc0, 0x47, 0xe0, + 0xe3, 0xff, 0xf1, 0xff, 0xf8, 0xff, 0xfc, 0xff }; + +static const gchar magmask_bits[] = { + 0x80, 0x1f, 0xc0, 0x3f, 0xe0, 0x70, 0x70, 0x66, 0x30, 0xc6, 0xb0, 0xdf, + 0xb0, 0xdf, 0x30, 0xc6, 0x70, 0xe6, 0xe0, 0x70, 0xf0, 0x3f, 0xb8, 0x1f, + 0x1c, 0x00, 0x0e, 0x00, 0x07, 0x00, 0x03, 0x00 }; + +/* Created with The GIMP */ +#define fader_cursor_width 25 +#define fader_cursor_height 25 +#define fader_cursor_x_hot 3 +#define fader_cursor_y_hot 21 +static const gchar fader_cursor_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x02, 0x01, + 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x01, + 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x01, + 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0xfe, 0x01, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, + 0x3e, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, 0x08, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + +/* Created with The GIMP */ +static const gchar fader_cursor_mask_bits[] = { + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01, + 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01, + 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01, + 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfe, 0x01, + 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, + 0x08, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x78, 0x00, 0x3e, 0x00, 0x78, 0x00, + 0x7f, 0x00, 0x78, 0x00, 0x3e, 0x00, 0x78, 0x00, 0x1c, 0x00, 0x78, 0x00, + 0x08, 0x00, 0x30, 0x00 }; + + +#define speaker_cursor_width 16 +#define speaker_cursor_height 26 +#define speaker_cursor_x_hot 0 +#define speaker_cursor_y_hot 0 +static const gchar speaker_cursor_bits[] = { + 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xcc, 0x00, 0xcc, + 0xff, 0xc3, 0xff, 0xc3, 0x03, 0xc0, 0x03, 0xc0, 0xc3, 0xc0, 0xc3, 0xc0, + 0xc3, 0xc0, 0xc3, 0xc0, 0xc3, 0xc0, 0xc3, 0xc0, 0x03, 0xc0, 0x03, 0xc0, + 0xff, 0xc3, 0xff, 0xc3, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xf0, 0x00, 0xf0, + 0x00, 0xc0, 0x00, 0xc0 }; + +#define speaker_cursor_mask_width 16 +#define speaker_cursor_mask_height 26 +#define speaker_cursor_mask_x_hot 0 +#define speaker_cursor_mask_y_hot 0 +static const gchar speaker_cursor_mask_bits[] = { + 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0xfc, + 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0x3f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xf0, 0x00, 0xf0, + 0x00, 0xc0, 0x00, 0xc0 }; + +/* XPM */ +static const gchar * zoom_in_button_xpm[] = { +"16 16 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" ....... ", +" .+++++++. ", +" .+++++++++. ", +" .+++.....+++. ", +" .+++. + .+++.", +" .++. +.+ .++.", +" .++. ++.++ .++.", +" .++.+.....+.++.", +" .++. ++.++ .++.", +" .++. +.+ .++.", +" .+++. + .+++.", +" .+++.....+++. ", +" .+++++++++++. ", +".+++.+++++++. ", +".++. ....... ", +"... "}; + +/* XPM */ +static const gchar * zoom_out_button_xpm[] = { +"16 16 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" ....... ", +" .+++++++. ", +" .+++++++++. ", +" .+++.....+++. ", +" .+++. .+++.", +" .++. .++.", +" .++. +++++ .++.", +" .++.+.....+.++.", +" .++. +++++ .++.", +" .++. .++.", +" .+++. .+++.", +" .+++.....+++. ", +" .+++++++++++. ", +".+++.+++++++. ", +".++. ....... ", +"... "}; + +/* XPM */ +static const gchar * zoom_out_full_button_xpm[] = { +"16 16 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" ", +" ", +" ", +" ", +".... ....", +".++. .++.", +".++..........++.", +".++++++++++++++.", +".++++++++++++++.", +".++++++++++++++.", +".++..........++.", +".++. .++.", +".... ....", +" ", +" ", +" "}; + +/* XPM */ +static const gchar * right_arrow_xpm[] = { +"12 15 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" .+.. ", +" .++.. ", +" .+++.. ", +" ..+++.. ", +" ..+++.. ", +" ..+++.. ", +" ..+++.. ", +" ..+++. ", +" ..+++.. ", +" ..+++.. ", +" ..+++.. ", +" ..+++.. ", +" .+++.. ", +" .++.. ", +" .+.. "}; + +/* XPM */ +static const gchar * left_arrow_xpm[] = { +"12 15 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" ..+. ", +" ..++. ", +" ..+++. ", +" ..+++.. ", +" ..+++.. ", +" ..+++.. ", +" ..+++.. ", +" .+++.. ", +" ..+++.. ", +" ..+++.. ", +" ..+++.. ", +" ..+++.. ", +" ..+++. ", +" ..++. ", +" ..+. "}; diff --git a/gtk2_ardour/enums.h b/gtk2_ardour/enums.h new file mode 100644 index 0000000000..514a821662 --- /dev/null +++ b/gtk2_ardour/enums.h @@ -0,0 +1,26 @@ +#ifndef __ardour_gtk_enums_h__ +#define __ardour_gtk_enums_h__ + +#include + +enum WaveformShape { + Traditional, + Rectified +}; + + +enum Width { + Wide, + Narrow, +}; + +#include + +struct SelectionRect { + GtkCanvasItem *rect; + GtkCanvasItem *end_trim; + GtkCanvasItem *start_trim; + uint32_t id; +}; + +#endif /* __ardour_gtk_enums_h__ */ diff --git a/gtk2_ardour/export_dialog.cc b/gtk2_ardour/export_dialog.cc new file mode 100644 index 0000000000..8a76e6c794 --- /dev/null +++ b/gtk2_ardour/export_dialog.cc @@ -0,0 +1,1391 @@ +/* + Copyright (C) 1999-2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include + +#include + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "export_dialog.h" +#include "check_mark.h" +#include "ardour_ui.h" +#include "public_editor.h" +#include "keyboard.h" + +#include "i18n.h" + +#define FRAME_SHADOW_STYLE GTK_SHADOW_IN +#define FRAME_NAME "BaseFrame" + +GdkPixmap* ExportDialog::check_pixmap = 0; +GdkPixmap* ExportDialog::check_mask = 0; +GdkPixmap* ExportDialog::empty_pixmap = 0; +GdkPixmap* ExportDialog::empty_mask = 0; + +using namespace std; + +using namespace ARDOUR; +using namespace SigC; +using namespace Gtk; + +static const gchar *sample_rates[] = { + N_("22.05kHz"), + N_("44.1kHz"), + N_("48kHz"), + N_("88.2kHz"), + N_("96kHz"), + N_("192kHz"), + 0 +}; + +static const gchar *src_qualities[] = { + N_("best"), + N_("fastest"), + N_("linear"), + N_("better"), + N_("intermediate"), + 0 +}; + +static const gchar *dither_types[] = { + N_("None"), + N_("Rectangular"), + N_("Shaped Noise"), + N_("Triangular"), + 0 +}; + +static const gchar* channel_strings[] = { + N_("stereo"), + N_("mono"), + 0 +}; + +static const gchar* cue_file_types[] = { + N_("None"), + N_("CUE"), + N_("TOC"), + 0 +}; + +ExportDialog::ExportDialog(PublicEditor& e, AudioRegion* r) + : ArdourDialog ("export dialog"), + editor (e), + format_table (9, 2), + format_frame (_("FORMAT")), + sample_rate_label (_("SAMPLE RATE")), + src_quality_label (_("CONVERSION QUALITY")), + dither_type_label (_("DITHER TYPE")), + cue_file_label (_("CD MARKER FILE TYPE")), + channel_count_label (_("CHANNELS")), + header_format_label (_("FILE TYPE")), + bitdepth_format_label (_("SAMPLE FORMAT")), + endian_format_label (_("SAMPLE ENDIANNESS")), + cuefile_only_checkbox (_("EXPORT CD MARKER FILE ONLY")), + file_frame (_("EXPORT TO FILE")), + file_browse_button (_("Browse")), + ok_button (_("Export")), + track_selector_button (_("Specific tracks ...")), + track_selector (3), + master_selector (3) +{ + guint32 n; + guint32 len; + guint32 maxlen; + + audio_region = r; + + session = 0; + + set_title (_("ardour: export")); + set_wmclass (_("ardour_export"), "Ardour"); + set_name ("ExportWindow"); + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK); + + add (vpacker); + + vpacker.set_border_width (10); + vpacker.set_spacing (10); + + file_selector = 0; + spec.running = false; + + file_entry.focus_in_event.connect (slot (ARDOUR_UI::generic_focus_in_event)); + file_entry.focus_out_event.connect (slot (ARDOUR_UI::generic_focus_out_event)); + + file_entry.set_name ("ExportFileNameEntry"); + + master_selector.set_name ("ExportTrackSelector"); + master_selector.set_usize (-1, 100); + master_selector.set_column_min_width (0, 100); + master_selector.set_column_min_width (1, 40); + master_selector.set_column_auto_resize(1, true); + master_selector.set_column_min_width (2, 40); + master_selector.set_column_auto_resize(2, true); + master_selector.set_column_title (0, _("Output")); + master_selector.column_titles_show (); + master_selector.set_selection_mode (GTK_SELECTION_MULTIPLE); + master_selector.button_press_event.connect (slot (*this, &ExportDialog::master_selector_button_press_event)); + + track_selector.set_name ("ExportTrackSelector"); + track_selector.set_usize (-1, 130); + track_selector.set_column_min_width (0, 100); + track_selector.set_column_min_width (1, 40); + track_selector.set_column_auto_resize(1, true); + track_selector.set_column_min_width (2, 40); + track_selector.set_column_auto_resize(2, true); + track_selector.set_column_title (0, _("Track")); + track_selector.column_titles_show (); + track_selector.set_selection_mode (GTK_SELECTION_MULTIPLE); + track_selector.button_press_event.connect (slot (*this, &ExportDialog::track_selector_button_press_event)); + + check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, + gtk_widget_get_colormap(GTK_WIDGET(track_selector.gtkobj())), + &check_mask, NULL, (gchar**) check_xpm); + empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, + gtk_widget_get_colormap(GTK_WIDGET(track_selector.gtkobj())), + &empty_mask, NULL, (gchar**) empty_xpm); + + progress_bar.set_show_text (false); + progress_bar.set_orientation (GTK_PROGRESS_LEFT_TO_RIGHT); + progress_bar.set_name ("ExportProgress"); + + format_frame.add (format_table); + format_frame.set_name (FRAME_NAME); + + track_scroll.set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + master_scroll.set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + vpacker.pack_start (file_frame, false, false); + + hpacker.set_spacing (5); + hpacker.set_border_width (5); + hpacker.pack_start (format_frame, false, false); + + if (!audio_region) { + + master_scroll.add (master_selector); + track_scroll.add (track_selector); + + master_scroll.set_usize (220, 100); + track_scroll.set_usize (220, 100); + + + + /* we may hide some of these later */ + track_vpacker.pack_start (master_scroll, true, true); + track_vpacker.pack_start (track_scroll, true, true); + track_vpacker.pack_start (track_selector_button, false); + + hpacker.pack_start (track_vpacker, true, true); + } + + vpacker.pack_start (hpacker, true, true); + + track_selector_button.set_name ("EditorGTKButton"); + track_selector_button.clicked.connect (slot (*this, &ExportDialog::track_selector_button_click)); + + vpacker.pack_start (button_box, false, false); + vpacker.pack_start (progress_bar, false, false); + + Gtkmmext::set_usize_to_display_given_text (file_entry, X_("Kg/quite/a/reasonable/size/for/files/i/think"), 5, 8); + + file_hbox.set_spacing (5); + file_hbox.set_border_width (5); + file_hbox.pack_start (file_entry, true, true); + file_hbox.pack_start (file_browse_button, false, false); + + file_frame.add (file_hbox); + file_frame.set_border_width (5); + file_frame.set_name (FRAME_NAME); + + sample_rate_combo.set_popdown_strings (internationalize(sample_rates)); + src_quality_combo.set_popdown_strings (internationalize (src_qualities)); + dither_type_combo.set_popdown_strings (internationalize (dither_types)); + channel_count_combo.set_popdown_strings (internationalize (channel_strings)); + header_format_combo.set_popdown_strings (internationalize ((const char **) sndfile_header_formats_strings)); + bitdepth_format_combo.set_popdown_strings (internationalize ((const char **) sndfile_bitdepth_formats_strings)); + endian_format_combo.set_popdown_strings (internationalize ((const char **) sndfile_endian_formats_strings)); + cue_file_combo.set_popdown_strings (internationalize (cue_file_types)); + + /* this will re-sensitized as soon as a non RIFF/WAV + header format is chosen. + */ + + endian_format_combo.set_sensitive (false); + + /* determine longest strings at runtime */ + + const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button + + maxlen = 0; + const char *longest = "gl"; + string longest_str; + + for (n = 0; n < SNDFILE_HEADER_FORMATS; ++n) { + if ((len = strlen (sndfile_header_formats_strings[n])) > maxlen) { + maxlen = len; + longest = sndfile_header_formats_strings[n]; + } + } + + for (n = 0; n < SNDFILE_BITDEPTH_FORMATS; ++n) { + if ((len = strlen (sndfile_bitdepth_formats_strings[n])) > maxlen) { + maxlen = len; + longest = sndfile_bitdepth_formats_strings[n]; + } + } + + for (n = 0; n < SNDFILE_ENDIAN_FORMATS; ++n) { + if ((len = strlen (sndfile_endian_formats_strings[n])) > maxlen) { + maxlen = len; + longest = sndfile_endian_formats_strings[n]; + } + } + + longest_str = longest; + + /* force ascender + descender */ + + longest_str[0] = 'g'; + longest_str[1] = 'l'; + + Gtkmmext::set_usize_to_display_given_text (*header_format_combo.get_entry(), longest_str.c_str(), 5+FUDGE, 5); + + // TRANSLATORS: "slereg" is "stereo" with ascender and descender substituted + Gtkmmext::set_usize_to_display_given_text (*channel_count_combo.get_entry(), _("slereg"), 5+FUDGE, 5); + + header_format_combo.set_use_arrows_always (true); + bitdepth_format_combo.set_use_arrows_always (true); + endian_format_combo.set_use_arrows_always (true); + channel_count_combo.set_use_arrows_always (true); + src_quality_combo.set_use_arrows_always (true); + dither_type_combo.set_use_arrows_always (true); + sample_rate_combo.set_use_arrows_always (true); + cue_file_combo.set_use_arrows_always (true); + + header_format_combo.set_value_in_list (true, false); + bitdepth_format_combo.set_value_in_list (true, false); + endian_format_combo.set_value_in_list (true, false); + channel_count_combo.set_value_in_list (true, false); + src_quality_combo.set_value_in_list (true, false); + dither_type_combo.set_value_in_list (true, false); + sample_rate_combo.set_value_in_list (true, false); + cue_file_combo.set_value_in_list (true, false); + + header_format_combo.get_entry()->set_editable (false); + bitdepth_format_combo.get_entry()->set_editable (false); + endian_format_combo.get_entry()->set_editable (false); + channel_count_combo.get_entry()->set_editable (false); + src_quality_combo.get_entry()->set_editable (false); + dither_type_combo.get_entry()->set_editable (false); + sample_rate_combo.get_entry()->set_editable (false); + cue_file_combo.get_entry()->set_editable (false); + + dither_type_label.set_name ("ExportFormatLabel"); + sample_rate_label.set_name ("ExportFormatLabel"); + src_quality_label.set_name ("ExportFormatLabel"); + channel_count_label.set_name ("ExportFormatLabel"); + header_format_label.set_name ("ExportFormatLabel"); + bitdepth_format_label.set_name ("ExportFormatLabel"); + endian_format_label.set_name ("ExportFormatLabel"); + cue_file_label.set_name ("ExportFormatLabel"); + + header_format_combo.get_entry()->set_name ("ExportFormatDisplay"); + bitdepth_format_combo.get_entry()->set_name ("ExportFormatDisplay"); + endian_format_combo.get_entry()->set_name ("ExportFormatDisplay"); + channel_count_combo.get_entry()->set_name ("ExportFormatDisplay"); + dither_type_combo.get_entry()->set_name ("ExportFormatDisplay"); + src_quality_combo.get_entry()->set_name ("ExportFormatDisplay"); + sample_rate_combo.get_entry()->set_name ("ExportFormatDisplay"); + cue_file_combo.get_entry()->set_name ("ExportFormatDisplay"); + + cuefile_only_checkbox.set_name ("ExportCheckbox"); + + format_table.set_homogeneous (true); + format_table.set_border_width (5); + format_table.set_col_spacings (5); + format_table.set_row_spacings (5); + + if (!audio_region) { + format_table.attach (channel_count_label, 0, 1, 0, 1); + format_table.attach (channel_count_combo, 0, 1, 1, 2); + } + + format_table.attach (header_format_label, 1, 2, 0, 1); + format_table.attach (header_format_combo, 1, 2, 1, 2); + + format_table.attach (bitdepth_format_label, 0, 1, 2, 3); + format_table.attach (bitdepth_format_combo, 0, 1, 3, 4); + + format_table.attach (endian_format_label, 1, 2, 2, 3); + format_table.attach (endian_format_combo, 1, 2, 3, 4); + + format_table.attach (sample_rate_label, 0, 1, 4, 5); + format_table.attach (sample_rate_combo, 0, 1, 5, 6); + + format_table.attach (src_quality_label, 1, 2, 4, 5); + format_table.attach (src_quality_combo, 1, 2, 5, 6); + + format_table.attach (dither_type_label, 0, 1, 6, 7); + format_table.attach (dither_type_combo, 0, 1, 7, 8); + + format_table.attach (cue_file_label, 1, 2, 6, 7); + format_table.attach (cue_file_combo, 1, 2, 7, 8); + format_table.attach (cuefile_only_checkbox, 1, 2, 8, 9); + + + button_box.set_spacing (10); + button_box.set_homogeneous (true); + + cancel_button.add (cancel_label); + + button_box.pack_start (ok_button, false, true); + button_box.pack_start (cancel_button, false, true); + + ok_button.set_name ("EditorGTKButton"); + cancel_button.set_name ("EditorGTKButton"); + file_entry.set_name ("ExportFileDisplay"); + + delete_event.connect (slot (*this, &ExportDialog::window_closed)); + ok_button.clicked.connect (slot (*this, &ExportDialog::do_export)); + cancel_button.clicked.connect (slot (*this, &ExportDialog::end_dialog)); + + file_browse_button.set_name ("EditorGTKButton"); + file_browse_button.clicked.connect (slot (*this, &ExportDialog::initiate_browse)); + + channel_count_combo.get_popwin()->unmap_event.connect (slot (*this, &ExportDialog::channels_chosen)); + bitdepth_format_combo.get_popwin()->unmap_event.connect (slot (*this, &ExportDialog::bitdepth_chosen)); + header_format_combo.get_popwin()->unmap_event.connect (slot (*this, &ExportDialog::header_chosen)); + sample_rate_combo.get_popwin()->unmap_event.connect (slot (*this, &ExportDialog::sample_rate_chosen)); + cue_file_combo.get_popwin()->unmap_event.connect (slot (*this, &ExportDialog::cue_file_type_chosen)); +} + +ExportDialog::~ExportDialog() +{ + if (file_selector) { + delete file_selector; + } +} + +void +ExportDialog::connect_to_session (Session *s) +{ + session = s; + session->going_away.connect (slot (*this, &Window::hide_all)); + + switch (session->frame_rate()) { + case 22050: + sample_rate_combo.get_entry()->set_text (N_("22.05kHz")); + break; + case 44100: + sample_rate_combo.get_entry()->set_text (N_("44.1kHz")); + break; + case 48000: + sample_rate_combo.get_entry()->set_text (N_("48kHz")); + break; + case 88200: + sample_rate_combo.get_entry()->set_text (N_("88.2kHz")); + break; + case 96000: + sample_rate_combo.get_entry()->set_text (N_("96kHz")); + break; + case 192000: + sample_rate_combo.get_entry()->set_text (N_("192kHz")); + break; + default: + sample_rate_combo.get_entry()->set_text (N_("44.1kHz")); + break; + } + + src_quality_combo.set_sensitive (false); + + set_state(); +} + +void +ExportDialog::set_state() +{ + XMLNode* node = session->instant_xml(X_("ExportDialog"), session->path()); + XMLProperty* prop; + + if (node) { + + if ((prop = node->property (X_("sample_rate"))) != 0) { + sample_rate_combo.get_entry()->set_text(prop->value()); + } + if ((prop = node->property (X_("src_quality"))) != 0) { + src_quality_combo.get_entry()->set_text(prop->value()); + } + if ((prop = node->property (X_("dither_type"))) != 0) { + dither_type_combo.get_entry()->set_text(prop->value()); + } + if ((prop = node->property (X_("channel_count"))) != 0) { + channel_count_combo.get_entry()->set_text(prop->value()); + } + if ((prop = node->property (X_("header_format"))) != 0) { + header_format_combo.get_entry()->set_text(prop->value()); + } + if ((prop = node->property (X_("bitdepth_format"))) != 0) { + bitdepth_format_combo.get_entry()->set_text(prop->value()); + } + if ((prop = node->property (X_("endian_format"))) != 0) { + endian_format_combo.get_entry()->set_text(prop->value()); + } + if ((prop = node->property (X_("filename"))) != 0) { + file_entry.set_text(prop->value()); + } + if ((prop = node->property (X_("cue_file_type"))) != 0) { + cue_file_combo.get_entry()->set_text(prop->value()); + } + } + + header_chosen (0); + bitdepth_chosen(0); + channels_chosen(0); + sample_rate_chosen(0); + + if (session->master_out()) { + track_scroll.hide (); + } else { + master_scroll.hide (); + track_selector_button.hide (); + } + + if (!node) { + return; + } + + if (session->master_out()) { + XMLNode* master = find_named_node(*node, (X_("Master"))); + int nchns; + + if (!master) { + + /* default is to use all */ + if (channel_count_combo.get_entry()->get_text() == _("mono")) { + nchns = 1; + } else { + nchns = 2; + } + + for (uint32_t r = 0; r < session->master_out()->n_outputs(); ++r) { + if (nchns == 2) { + if (r % 2) { + master_selector.cell (r, 2).set_pixmap (check_pixmap, check_mask); + } else { + master_selector.cell (r, 1).set_pixmap (check_pixmap, check_mask); + } + } else { + master_selector.cell (r, 1).set_pixmap (check_pixmap, check_mask); + } + } + + } else { + /* XXX use XML state */ + } + } + + XMLNode* tracks = find_named_node(*node, (X_("Tracks"))); + if (!tracks) { + return; + } + + XMLNodeList track_list = tracks->children(X_("Track")); + CList_Helpers::RowIterator ri = track_selector.rows().begin(); + uint32_t n = 0; + for (XMLNodeIterator it = track_list.begin(); it != track_list.end(); ++it, ++ri, ++n) { + if (ri == track_selector.rows().end()) { + break; + } + + XMLNode* track = *it; + + if ((prop = track->property(X_("channel1"))) != 0) { + if (prop->value() == X_("on")) { + track_selector.cell (n,1).set_pixmap (check_pixmap, check_mask); + } else { + track_selector.cell (n,1).set_pixmap (empty_pixmap, empty_mask); + } + } + + if ((prop = track->property(X_("channel2"))) != 0) { + if (prop->value() == X_("on")) { + track_selector.cell (n,2).set_pixmap (check_pixmap, check_mask); + } else { + track_selector.cell (n,2).set_pixmap (empty_pixmap, empty_mask); + } + } + } + } + +void +ExportDialog::save_state() +{ + if (!session) { + return; + } + + XMLNode* node = new XMLNode(X_("ExportDialog")); + + node->add_property(X_("sample_rate"), sample_rate_combo.get_entry()->get_text()); + node->add_property(X_("src_quality"), src_quality_combo.get_entry()->get_text()); + node->add_property(X_("dither_type"), dither_type_combo.get_entry()->get_text()); + node->add_property(X_("channel_count"), channel_count_combo.get_entry()->get_text()); + node->add_property(X_("header_format"), header_format_combo.get_entry()->get_text()); + node->add_property(X_("bitdepth_format"), bitdepth_format_combo.get_entry()->get_text()); + node->add_property(X_("endian_format"), endian_format_combo.get_entry()->get_text()); + node->add_property(X_("filename"), file_entry.get_text()); + node->add_property(X_("cue_file_type"), cue_file_combo.get_entry()->get_text()); + + XMLNode* tracks = new XMLNode(X_("Tracks")); + + uint32_t n = 0; + for (CList_Helpers::RowIterator ri = track_selector.rows().begin(); ri != track_selector.rows().end(); ++ri, ++n) { + XMLNode* track = new XMLNode(X_("Track")); + + Gdk_Pixmap left_pixmap = track_selector.cell (n, 1).get_pixmap (); + track->add_property(X_("channel1"), left_pixmap.gdkobj() == check_pixmap ? X_("on") : X_("off")); + + Gdk_Pixmap right_pixmap = track_selector.cell (n, 2).get_pixmap (); + track->add_property(X_("channel2"), right_pixmap.gdkobj() == check_pixmap ? X_("on") : X_("off")); + + tracks->add_child_nocopy(*track); + } + node->add_child_nocopy(*tracks); + + session->add_instant_xml(*node, session->path()); +} + +void +ExportDialog::set_range (jack_nframes_t start, jack_nframes_t end) +{ + spec.start_frame = start; + spec.end_frame = end; + + if (!audio_region) { + // XXX: this is a hack until we figure out what is really wrong + session->request_locate (spec.start_frame, false); + } +} + +gint +ExportDialog::progress_timeout () +{ + progress_bar.set_percentage (spec.progress); + return TRUE; +} + +void* +ExportDialog::_export_region_thread (void *arg) +{ + PBD::ThreadCreated (pthread_self(), X_("Export Region")); + + static_cast(arg)->export_region (); + return 0; +} + +void +ExportDialog::export_region () +{ + audio_region->exportme (*session, spec); +} + +void +frames_to_cd_frames_string (char* buf, jack_nframes_t when, jack_nframes_t fr) +{ + + long unsigned int remainder; + int mins, secs, frames; + + mins = when / (60 * fr); + remainder = when - (mins * 60 * fr); + secs = remainder / fr; + remainder -= secs * fr; + frames = remainder / (fr / 75); + sprintf (buf, " %02d:%02d:%02d", mins, secs, frames); + +} + +struct LocationSortByStart { + bool operator() (Location *a, Location *b) { + return a->start() < b->start(); + } +}; + +void +ExportDialog::export_toc_file (Locations::LocationList& locations, const string& path) +{ + + string filepath = path + ".toc"; + ofstream out (filepath.c_str()); + long unsigned int last_end_time = spec.start_frame, last_start_time = spec.start_frame; + int numtracks = 0; + gchar buf[18]; + + if (!out) { + error << compose(_("Editor: cannot open \"%1\" as export file for CD toc file"), filepath) << endmsg; + return; + } + out << "CD_DA" << endl; + out << "CD_TEXT {" << endl << " LANGUAGE_MAP {" << endl << " 0 : EN" << endl << " }" << endl; + out << " LANGUAGE 0 {" << endl << " TITLE \"" << session->name() << "\"" << endl << " }" << endl << "}" << endl; + + Locations::LocationList::iterator i; + Locations::LocationList temp; + + for (i = locations.begin(); i != locations.end(); ++i) { + if ((*i)->start() >= spec.start_frame && (*i)->end() <= spec.end_frame && (*i)->is_cd_marker() && !(*i)->is_end()) { + temp.push_back (*i); + if (!(*i)->is_mark()) { + numtracks ++; + } + } + } + + if (numtracks == 0 ) { + /* the user supplied no track markers. + we now treat the session as one track.*/ + + out << endl << "TRACK AUDIO" << endl; + + out << "COPY" << endl; + + out << "NO PRE_EMPHASIS" << endl; + + /* XXX add session properties for catalog etc. + (so far only the session name is used) */ + + out << "CD_TEXT {" << endl << " LANGUAGE 0 {" << endl << " TITLE \"" << session->name() << "\"" << endl; + out << " }" << endl << "}" << endl; + + out << "FILE \"" << path << "\" "; + out << "00:00:00 " ; + frames_to_cd_frames_string (buf, spec.end_frame - spec.start_frame, session->frame_rate()); + out << buf << endl; + out << "START 00:00:00" << endl; + + last_start_time = spec.start_frame; + last_end_time = spec.end_frame; + } + + if (temp.size()) { + LocationSortByStart cmp; + temp.sort (cmp); + + for (i = temp.begin(); i != temp.end(); ++i) { + + if (!(*i)->is_mark()) { + /*this is a track */ + out << endl << "TRACK AUDIO" << endl; + + if ((*i)->cd_info.find("scms") != (*i)->cd_info.end()) { + out << "NO "; + } + out << "COPY" << endl; + + if ((*i)->cd_info.find("preemph") != (*i)->cd_info.end()) { + out << "PRE_EMPHASIS" << endl; + } else { + out << "NO PRE_EMPHASIS" << endl; + } + + if ((*i)->cd_info.find("isrc") != (*i)->cd_info.end()) { + out << "ISRC \"" << (*i)->cd_info["isrc"] << "\"" << endl; + } + + out << "CD_TEXT {" << endl << " LANGUAGE 0 {" << endl << " TITLE \"" << (*i)->name() << "\"" << endl; + if ((*i)->cd_info.find("performer") != (*i)->cd_info.end()) { + out << " PERFORMER \"" << (*i)->cd_info["performer"] << "\"" << endl; + } + if ((*i)->cd_info.find("composer") != (*i)->cd_info.end()) { + out << " COMPOSER \"" << (*i)->cd_info["composer"] << "\"" << endl; + } + + if ((*i)->cd_info.find("isrc") != (*i)->cd_info.end()) { + out << " ISRC \""; + out << (*i)->cd_info["isrc"].substr(0,2) << "-"; + out << (*i)->cd_info["isrc"].substr(2,3) << "-"; + out << (*i)->cd_info["isrc"].substr(5,2) << "-"; + out << (*i)->cd_info["isrc"].substr(7,5) << "\"" << endl; + } + + out << " }" << endl << "}" << endl; + + frames_to_cd_frames_string (buf, last_end_time - spec.start_frame, session->frame_rate()); + out << "FILE \"" << path << "\" " << buf; + + frames_to_cd_frames_string (buf, (*i)->end() - last_end_time, session->frame_rate()); + out << buf << endl; + + frames_to_cd_frames_string (buf, (*i)->start() - last_end_time, session->frame_rate()); + out << "START" << buf << endl; + + last_start_time = (*i)->start(); + last_end_time = (*i)->end(); + + + } else if ((*i)->start() < last_end_time) { + /* this is an index within a track */ + + frames_to_cd_frames_string (buf, (*i)->start() - last_start_time, session->frame_rate()); + out << "INDEX" << buf << endl; + } + } + } + +} + +void +ExportDialog::export_cue_file (Locations::LocationList& locations, const string& path) +{ + string filepath = path + ".cue"; + ofstream out (filepath.c_str()); + gchar buf[18]; + long unsigned int last_track_end = spec.start_frame; + int numtracks = 0, tracknum = 0, indexnum = 0; + + if (!out) { + error << compose(_("Editor: cannot open \"%1\" as export file for CD cue file"), filepath) << endmsg; + return; + } + + Locations::LocationList::iterator i; + Locations::LocationList temp; + + for (i = locations.begin(); i != locations.end(); ++i) { + if ((*i)->start() >= spec.start_frame && (*i)->end() <= spec.end_frame && (*i)->is_cd_marker() && !(*i)->is_end()) { + temp.push_back (*i); + if (!(*i)->is_mark()) { + numtracks++; + } + } + } + + out << "REM Cue file generated by Ardour" << endl; + out << "TITLE \"" << session->name() << "\"" << endl; + + if ((header_format_combo.get_entry()->get_text() == N_("WAV"))) { + out << "FILE " << path << " WAVE" << endl; + } else { + out << "FILE " << path << ' ' << (header_format_combo.get_entry()->get_text()) << endl; + } + + if (numtracks == 0) { + /* the user has supplied no track markers. + the entire export is treated as one track. + */ + + numtracks++; + tracknum++; + indexnum = 0; + out << endl << "TRACK " << tracknum << " AUDIO" << endl; + out << "FLAGS " ; + + out << "DCP " << endl; + + /* use the session name*/ + + if (session->name() != "") { + out << "TITLE \"" << session->name() << "\"" << endl; + } + + /* no pregap in this case */ + + out << "INDEX 00 00:00:00" << endl; + indexnum++; + out << "INDEX 01 00:00:00" << endl; + indexnum++; + last_track_end = spec.end_frame; + } + + if (temp.size()) { + LocationSortByStart cmp; + temp.sort (cmp); + + for ( i = temp.begin(); i != temp.end(); ++i) { + + if (!(*i)->is_mark() && ((*i)->start() >= last_track_end)) { + /* this is a track and it doesn't start inside another one*/ + + tracknum++; + indexnum = 0; + out << endl << "TRACK " << tracknum << " AUDIO" << endl; + out << "FLAGS " ; + + if ((*i)->cd_info.find("scms") != (*i)->cd_info.end()) { + out << "SCMS "; + } else { + out << "DCP "; + } + + if ((*i)->cd_info.find("preemph") != (*i)->cd_info.end()) { + out << "PRE"; + } + out << endl; + + if ((*i)->cd_info.find("isrc") != (*i)->cd_info.end()) { + out << "ISRC " << (*i)->cd_info["isrc"] << endl; + + } + if ((*i)->name() != "") { + out << "TITLE \"" << (*i)->name() << "\"" << endl; + } + + if ((*i)->cd_info.find("performer") != (*i)->cd_info.end()) { + out << "PERFORMER \"" << (*i)->cd_info["performer"] << "\"" << endl; + } + + if ((*i)->cd_info.find("composer") != (*i)->cd_info.end()) { + out << "SONGWRITER \"" << (*i)->cd_info["composer"] << "\"" << endl; + } + snprintf (buf, sizeof(buf), "INDEX %02d", indexnum); + out << buf; + frames_to_cd_frames_string (buf, last_track_end - spec.start_frame, session->frame_rate()); + out << buf << endl; + indexnum++; + last_track_end = (*i)->end(); + } + if ((tracknum > 0) && ((*i)->start() < last_track_end)) { + /*this is an index and it lies within a track*/ + snprintf (buf, sizeof(buf), "INDEX %02d", indexnum); + out << buf; + frames_to_cd_frames_string (buf,(*i)->start() - spec.start_frame, session->frame_rate()); + out << buf << endl; + indexnum++; + } + } + } + +} + +void +ExportDialog::do_export_cd_markers (const string& path,const string& cuefile_type) +{ + if (cuefile_type == "TOC") { + session->locations()->apply (*this, &ExportDialog::export_toc_file, path); + } else { + session->locations()->apply (*this, &ExportDialog::export_cue_file, path); + } +} + + +void +ExportDialog::do_export () +{ + using namespace CList_Helpers; + + ok_button.set_sensitive(false); + save_state(); + + if (cue_file_combo.get_entry()->get_text () != _("None")) { + do_export_cd_markers (file_entry.get_text(), cue_file_combo.get_entry()->get_text ()); + } + + if (cuefile_only_checkbox.get_active()) { + end_dialog (); + return; + } + + set_modal (true); + + spec.path = file_entry.get_text(); + spec.progress = 0; + spec.running = true; + spec.stop = false; + spec.port_map.clear(); + + if (channel_count_combo.get_entry()->get_text() == _("mono")) { + spec.channels = 1; + } else { + spec.channels = 2; + } + + spec.format = 0; + + spec.format |= sndfile_header_format_from_string (header_format_combo.get_entry()->get_text ()); + + if ((spec.format & SF_FORMAT_WAV) == 0) { + /* RIFF/WAV specifies endianess */ + spec.format |= sndfile_endian_format_from_string (endian_format_combo.get_entry()->get_text ()); + } + + spec.format |= sndfile_bitdepth_format_from_string (bitdepth_format_combo.get_entry()->get_text ()); + + string sr_str = sample_rate_combo.get_entry()->get_text(); + if (sr_str == N_("22.05kHz")) { + spec.sample_rate = 22050; + } else if (sr_str == N_("44.1kHz")) { + spec.sample_rate = 44100; + } else if (sr_str == N_("48kHz")) { + spec.sample_rate = 48000; + } else if (sr_str == N_("88.2kHz")) { + spec.sample_rate = 88200; + } else if (sr_str == N_("96kHz")) { + spec.sample_rate = 96000; + } else if (sr_str == N_("192kHz")) { + spec.sample_rate = 192000; + } else { + spec.sample_rate = session->frame_rate(); + } + + string src_str = src_quality_combo.get_entry()->get_text(); + if (src_str == _("fastest")) { + spec.src_quality = SRC_ZERO_ORDER_HOLD; + } else if (src_str == _("linear")) { + spec.src_quality = SRC_LINEAR; + } else if (src_str == _("better")) { + spec.src_quality = SRC_SINC_FASTEST; + } else if (src_str == _("intermediate")) { + spec.src_quality = SRC_SINC_MEDIUM_QUALITY; + } else { + spec.src_quality = SRC_SINC_BEST_QUALITY; + } + + string dither_str = dither_type_combo.get_entry()->get_text(); + if (dither_str == _("None")) { + spec.dither_type = GDitherNone; + } else if (dither_str == _("Rectangular")) { + spec.dither_type = GDitherRect; + } else if (dither_str == _("Triangular")) { + spec.dither_type = GDitherTri; + } else { + spec.dither_type = GDitherShaped; + } + + if (!audio_region) { + + uint32_t n = 0; + uint32_t chan=0; + Port *last_port = 0; + + for (RowIterator ri = master_selector.rows().begin(); ri != master_selector.rows().end(); ++ri, ++n) { + + Port* port = static_cast ((*ri)->get_data ()); + + if (last_port != port) { + chan = 0; + } + + Gdk_Pixmap left_pixmap = master_selector.cell (n, 1).get_pixmap (); + + if (left_pixmap.gdkobj() == check_pixmap) { + spec.port_map[0].push_back (std::pair(port, chan)); + } + + if (spec.channels == 2) { + + Gdk_Pixmap right_pixmap = master_selector.cell (n, 2).get_pixmap (); + + if (right_pixmap.gdkobj() == check_pixmap) { + spec.port_map[1].push_back (std::pair(port, chan)); + } + + } + } + + chan = 0; + n = 0; + + for (RowIterator ri = track_selector.rows().begin(); ri != track_selector.rows().end(); ++ri, ++n) { + + Port* port = static_cast ((*ri)->get_data ()); + + if (last_port != port) { + chan = 0; + } + + Gdk_Pixmap left_pixmap = track_selector.cell (n, 1).get_pixmap (); + + if (left_pixmap.gdkobj() == check_pixmap) { + spec.port_map[0].push_back (std::pair(port, chan)); + } + + if (spec.channels == 2) { + + Gdk_Pixmap right_pixmap = track_selector.cell (n, 2).get_pixmap (); + + if (right_pixmap.gdkobj() == check_pixmap) { + spec.port_map[1].push_back (std::pair(port, chan)); + } + + } + + last_port = port; + ++chan; + } + } + + progress_connection = Main::timeout.connect (slot (*this, &ExportDialog::progress_timeout), 100); + cancel_label.set_text (_("Stop Export")); + + if (!audio_region) { + if (session->start_audio_export (spec)) { + goto out; + } + } else { + pthread_t thr; + pthread_create_and_store ("region export", &thr, 0, ExportDialog::_export_region_thread, this); + } + + gtk_main_iteration (); + while (spec.running) { + if (gtk_events_pending()) { + gtk_main_iteration (); + } else { + usleep (10000); + } + } + + out: + progress_connection.disconnect (); + end_dialog (); +} + + +void +ExportDialog::end_dialog () +{ + + if (spec.running) { + spec.stop = true; + + while (spec.running) { + if (gtk_events_pending()) { + gtk_main_iteration (); + } else { + usleep (10000); + } + } + } + + session->engine().freewheel (false); + + hide_all (); + + if (file_selector) { + file_selector->hide_all (); + } + + set_modal (false); + ok_button.set_sensitive(true); +} + +void +ExportDialog::start_export () +{ + if (session == 0) { + return; + } + + /* If it the filename hasn't been set before, use the + directory above the current session as a default + location for the export. + */ + + if (file_entry.get_text().length() == 0) { + string dir = session->path(); + string::size_type last_slash; + + if ((last_slash = dir.find_last_of ('/')) != string::npos) { + dir = dir.substr (0, last_slash+1); + } + + file_entry.set_text (dir); + } + + progress_bar.set_percentage (0); + cancel_label.set_text (_("Cancel")); + + show_all (); + + if (session->master_out()) { + track_scroll.hide (); + } else { + master_scroll.hide (); + track_selector_button.hide (); + } +} + +gint +ExportDialog::header_chosen (GdkEventAny* ignored) +{ + if (sndfile_header_format_from_string (header_format_combo.get_entry()->get_text ()) == SF_FORMAT_WAV) { + endian_format_combo.set_sensitive (false); + } else { + endian_format_combo.set_sensitive (true); + } + return FALSE; +} + +gint +ExportDialog::bitdepth_chosen (GdkEventAny* ignored) +{ + int format = sndfile_bitdepth_format_from_string (bitdepth_format_combo.get_entry()->get_text ()); + switch (format) { + case SF_FORMAT_PCM_24: + case SF_FORMAT_PCM_32: + case SF_FORMAT_FLOAT: + dither_type_combo.set_sensitive (false); + break; + + default: + dither_type_combo.set_sensitive (true); + break; + } + + return FALSE; +} + +gint +ExportDialog::cue_file_type_chosen (GdkEventAny* ignored) +{ + if (cue_file_combo.get_entry()->get_text () != "None") { + cuefile_only_checkbox.set_sensitive (true); + } else { + cuefile_only_checkbox.set_active (false); + cuefile_only_checkbox.set_sensitive (false); + } + return FALSE; +} + +gint +ExportDialog::sample_rate_chosen (GdkEventAny* ignored) +{ + string sr_str = sample_rate_combo.get_entry()->get_text(); + jack_nframes_t rate; + + if (sr_str == N_("22.05kHz")) { + rate = 22050; + } else if (sr_str == N_("44.1kHz")) { + rate = 44100; + } else if (sr_str == N_("48kHz")) { + rate = 48000; + } else if (sr_str == N_("88.2kHz")) { + rate = 88200; + } else if (sr_str == N_("96kHz")) { + rate = 96000; + } else if (sr_str == N_("192kHz")) { + rate = 192000; + } else { + rate = session->frame_rate(); + } + + if (rate != session->frame_rate()) { + src_quality_combo.set_sensitive (true); + } else { + src_quality_combo.set_sensitive (false); + } + + return FALSE; +} + +gint +ExportDialog::channels_chosen (GdkEventAny* ignored) +{ + bool mono; + + mono = (channel_count_combo.get_entry()->get_text() == _("mono")); + + if (mono) { + track_selector.set_column_visibility (2, false); + track_selector.set_column_title (1, _("Export")); + + if (session->master_out()) { + master_selector.set_column_visibility (2, false); + master_selector.set_column_title (1, _("Export")); + } + + } else { + track_selector.set_column_visibility (2, true); + track_selector.set_column_title (1, _("Left")); + track_selector.set_column_title (2, _("Right")); + + if (session->master_out()) { + master_selector.set_column_visibility (2, true); + master_selector.set_column_title (1, _("Left")); + master_selector.set_column_title (2, _("Right")); + } + } + + track_selector.column_titles_show (); + track_selector.clear (); + master_selector.column_titles_show (); + master_selector.clear (); + + Session::RouteList routes = session->get_routes (); + + for (Session::RouteList::iterator ri = routes.begin(); ri != routes.end(); ++ri) { + + Route* route = (*ri); + + if (route->hidden()) { + continue; + } + + for (uint32_t i=0; i < route->n_outputs(); ++i) { + + list stupid_list; + + if (route->n_outputs() == 1) { + stupid_list.push_back (route->name()); + } else { + stupid_list.push_back (compose("%1: out-%2", route->name(), i+1)); + } + + stupid_list.push_back (""); + stupid_list.push_back (""); + + if (route == session->master_out()) { + master_selector.rows().push_back (stupid_list); + CList_Helpers::Row row = master_selector.rows().back(); + row.set_data (route->output (i)); + master_selector.cell (row.get_row_num(), 1).set_pixmap (empty_pixmap, empty_mask); + master_selector.cell (row.get_row_num(), 2).set_pixmap (empty_pixmap, empty_mask); + } else { + track_selector.rows().push_back (stupid_list); + CList_Helpers::Row row = track_selector.rows().back(); + row.set_data (route->output (i)); + track_selector.cell (row.get_row_num(), 1).set_pixmap (empty_pixmap, empty_mask); + track_selector.cell (row.get_row_num(), 2).set_pixmap (empty_pixmap, empty_mask); + } + } + } + + track_selector.select_all (); + master_selector.select_all (); + + return FALSE; +} + +gint +ExportDialog::track_selector_button_press_event (GdkEventButton* ev) +{ + gint row, col; + + if (track_selector.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) { + return FALSE; + } + + gtk_signal_emit_stop_by_name (GTK_OBJECT(track_selector.gtkobj()), "button_press_event"); + + Gdk_Pixmap pixmap = track_selector.cell (row,col).get_pixmap (); + + if (col != 0) { + if (pixmap.gdkobj() == check_pixmap) { + track_selector.cell (row,col).set_pixmap (empty_pixmap, empty_mask); + } else { + track_selector.cell (row,col).set_pixmap (check_pixmap, check_mask); + } + } + + return TRUE; +} + +gint +ExportDialog::master_selector_button_press_event (GdkEventButton* ev) +{ + gint row, col; + + if (master_selector.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) { + return FALSE; + } + + gtk_signal_emit_stop_by_name (GTK_OBJECT(master_selector.gtkobj()), "button_press_event"); + + if (col != 0) { + Gdk_Pixmap pixmap = master_selector.cell (row,col).get_pixmap (); + + if (pixmap.gdkobj() == check_pixmap) { + master_selector.cell (row,col).set_pixmap (empty_pixmap, empty_mask); + } else { + master_selector.cell (row,col).set_pixmap (check_pixmap, check_mask); + } + } + + return TRUE; +} + +gint +ExportDialog::window_closed (GdkEventAny *ignored) +{ + end_dialog (); + return TRUE; +} +void +ExportDialog::initiate_browse () +{ + if (file_selector == 0) { + file_selector = new FileSelection; + file_selector->set_modal (true); + + file_selector->get_cancel_button()->clicked.connect (bind (slot (*this, &ExportDialog::finish_browse), -1)); + file_selector->get_ok_button()->clicked.connect (bind (slot (*this, &ExportDialog::finish_browse), 1)); + file_selector->map_event.connect (bind (slot (*this, &ExportDialog::change_focus_policy), true)); + file_selector->unmap_event.connect (bind (slot (*this, &ExportDialog::change_focus_policy), false)); + } + file_selector->show_all (); +} + +gint +ExportDialog::change_focus_policy (GdkEventAny *ev, bool yn) +{ + Keyboard::the_keyboard().allow_focus (yn); + return FALSE; +} + +void +ExportDialog::finish_browse (int status) +{ + if (file_selector) { + if (status > 0) { + string result = file_selector->get_filename(); + + if (result.length()) { + file_entry.set_text (result); + } + } + file_selector->hide_all(); + } +} + +void +ExportDialog::track_selector_button_click () +{ + if (track_scroll.is_visible ()) { + track_scroll.hide (); + } else { + track_scroll.show_all (); + } +} diff --git a/gtk2_ardour/export_dialog.h b/gtk2_ardour/export_dialog.h new file mode 100644 index 0000000000..f974af26a1 --- /dev/null +++ b/gtk2_ardour/export_dialog.h @@ -0,0 +1,132 @@ +/* + Copyright (C) 1999-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_export_dialog_h__ +#define __ardour_export_dialog_h__ + +#include + +#include +#include "ardour_dialog.h" +#include + + +class PublicEditor; + +namespace ARDOUR { + class Session; + class AudioRegion; +} + +class ExportDialog : public ArdourDialog +{ + public: + ExportDialog (PublicEditor&, ARDOUR::AudioRegion* r = 0); + ~ExportDialog (); + + void connect_to_session (ARDOUR::Session*); + void set_range (jack_nframes_t start, jack_nframes_t end); + void start_export (); + + private: + PublicEditor& editor; + ARDOUR::Session* session; + ARDOUR::AudioRegion* audio_region; + Gtk::VBox vpacker; + Gtk::VBox track_vpacker; + Gtk::HBox hpacker; + Gtk::HBox button_box; + + Gtk::Table format_table; + Gtk::Frame format_frame; + + Gtk::Label sample_rate_label; + Gtk::Combo sample_rate_combo; + Gtk::Label src_quality_label; + Gtk::Combo src_quality_combo; + Gtk::Label dither_type_label; + Gtk::Combo dither_type_combo; + Gtk::Label cue_file_label; + Gtk::Combo cue_file_combo; + Gtk::Label channel_count_label; + Gtk::Combo channel_count_combo; + Gtk::Label header_format_label; + Gtk::Combo header_format_combo; + Gtk::Label bitdepth_format_label; + Gtk::Combo bitdepth_format_combo; + Gtk::Label endian_format_label; + Gtk::Combo endian_format_combo; + Gtk::CheckButton cuefile_only_checkbox; + + Gtk::Frame file_frame; + Gtk::Entry file_entry; + Gtk::HBox file_hbox; + Gtk::Button file_browse_button; + + Gtk::Button ok_button; + Gtk::Button cancel_button; + Gtk::Label cancel_label; + Gtk::ProgressBar progress_bar; + Gtk::ScrolledWindow track_scroll; + Gtk::ScrolledWindow master_scroll; + Gtk::Button track_selector_button; + Gtk::CList track_selector; + Gtk::CList master_selector; + Gtk::FileSelection *file_selector; + ARDOUR::AudioExportSpecification spec; + + static GdkPixmap *check_pixmap; + static GdkBitmap *check_mask; + static GdkPixmap *empty_pixmap; + static GdkBitmap *empty_mask; + + static void *_thread (void *arg); + gint progress_timeout (); + SigC::Connection progress_connection; + void build_window (); + void end_dialog(); + gint header_chosen (GdkEventAny *ignored); + gint channels_chosen (GdkEventAny *ignored); + gint bitdepth_chosen (GdkEventAny *ignored); + gint sample_rate_chosen (GdkEventAny *ignored); + gint cue_file_type_chosen(GdkEventAny *ignored); + gint track_selector_button_press_event (GdkEventButton *ev); + gint master_selector_button_press_event (GdkEventButton *ev); + + void do_export_cd_markers (const string& path, const string& cuefile_type); + void export_cue_file (ARDOUR::Locations::LocationList& locations, const string& path); + void export_toc_file (ARDOUR::Locations::LocationList& locations, const string& path); + void do_export (); + gint change_focus_policy (GdkEventAny *, bool); + gint window_closed (GdkEventAny *ignored); + + void track_selector_button_click (); + + void initiate_browse (); + void finish_browse (int status); + + void set_state(); + void save_state(); + + static void* _export_region_thread (void *); + void export_region (); +}; + +#endif // __ardour_export_dialog_h__ + diff --git a/gtk2_ardour/extra_bind.h b/gtk2_ardour/extra_bind.h new file mode 100644 index 0000000000..70e1c3e538 --- /dev/null +++ b/gtk2_ardour/extra_bind.h @@ -0,0 +1,138 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_extra_bind_h__ +#define __ardour_extra_bind_h__ + +#include +#include + +namespace SigC +{ + +/**************************************************************** + ***** Adaptor Bind Slot 0 arguments, 3 hidden arguments + ****************************************************************/ +template +struct AdaptorBindSlot0_3: public AdaptorSlot_ + { +#ifdef SIGC_CXX_PARTIAL_SPEC + typedef R RType; +#else + typedef typename Trait::type RType; +#endif + typedef Slot0 SlotType; + typedef Slot3 InSlotType; + + struct Node:public AdaptorNode + { + C1 c1_; + C2 c2_; + C3 c3_; + }; + + typedef CallDataObj2 CallData; + + static RType callback(void* d) + { + CallData* data=(CallData*)d; + Node* node=data->obj; + return ((typename InSlotType::Callback&)(node->data_))( + node->c1_, + node->c2_, + node->c3_); + } + static SlotData* create(SlotData *s,C1 c1, C2 c2, C3 c3) + { + SlotData* tmp=(SlotData*)s; + Node *node=new Node(); + copy_callback(tmp,node); + node->c1_=c1; + node->c2_=c2; + node->c3_=c3; + CallData &data=reinterpret_cast(tmp->data_); + data.callback=&callback; + data.obj=node; + return tmp; + } + }; + + +#ifndef SIGC_CXX_VOID_RETURN +#ifdef SIGC_CXX_PARTIAL_SPEC +template < + class C1,C2,C3> +struct AdaptorBindSlot0_3 + : public AdaptorSlot_ + { + typedef void RType; + typedef Slot0 SlotType; + typedef Slot3 InSlotType; + + struct Node:public AdaptorNode + { + C1 c1_; + C2 c2_; + C3 c3_; + }; + + typedef CallDataObj2 CallData; + + static RType callback(void* d) + { + CallData* data=(CallData*)d; + Node* node=data->obj; + ((typename InSlotType::Callback&)(node->data_))( + node->c1_, + node->c2_, + node->c3); + } + static SlotData* create(SlotData *s,C1 c1, C2 c2, C3 c3) + { + SlotData* tmp=(SlotData*)s; + Node *node=new Node(); + copy_callback(tmp,node); + node->c1_=c1; + node->c2_=c2; + node->c3_=c3; + CallData &data=reinterpret_cast(tmp->data_); + data.callback=&callback; + data.obj=node; + return tmp; + } + }; + +#endif +#endif + +template +Slot0 + bind(const Slot3 &s, + C1 c1, C2 c2, C3 c3) + {return AdaptorBindSlot0_3::create(s.data(),c1,c2,c3); + } + +} /* namespace */ + +#endif /* __ardour_extra_bind_h__ */ diff --git a/gtk2_ardour/gain_automation_time_axis.cc b/gtk2_ardour/gain_automation_time_axis.cc new file mode 100644 index 0000000000..2f739e0fad --- /dev/null +++ b/gtk2_ardour/gain_automation_time_axis.cc @@ -0,0 +1,75 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include "gain_automation_time_axis.h" +#include "automation_line.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; + +GainAutomationTimeAxisView::GainAutomationTimeAxisView (Session& s, Route& r, PublicEditor& e, TimeAxisView& parent, Widget* p, std::string n, ARDOUR::Curve& c) + + : AxisView (s), + AutomationTimeAxisView (s, r, e, parent, p, n, X_("gain"), ""), + curve (c) + +{ +} + +GainAutomationTimeAxisView::~GainAutomationTimeAxisView () +{ +} + +void +GainAutomationTimeAxisView::add_automation_event (GtkCanvasItem* item, GdkEvent* event, jack_nframes_t when, double y) +{ + double x = 0; + + gtk_canvas_item_w2i (canvas_display, &x, &y); + + /* compute vertical fractional position */ + + y = 1.0 - (y / height); + + /* map using line */ + + lines.front()->view_to_model_y (y); + + _session.begin_reversible_command (_("add gain automation event")); + + _session.add_undo (curve.get_memento()); + curve.add (when, y); + _session.add_redo_no_execute (curve.get_memento()); + _session.commit_reversible_command (); + _session.set_dirty (); +} + +void +GainAutomationTimeAxisView::set_automation_state (AutoState state) +{ + if (!ignore_state_request) { + route.set_gain_automation_state (state); + } +} diff --git a/gtk2_ardour/gain_automation_time_axis.h b/gtk2_ardour/gain_automation_time_axis.h new file mode 100644 index 0000000000..b261e34d30 --- /dev/null +++ b/gtk2_ardour/gain_automation_time_axis.h @@ -0,0 +1,33 @@ +#ifndef __ardour_gtk_gain_automation_time_axis_h__ +#define __ardour_gtk_gain_automation_time_axis_h__ + +#include "automation_time_axis.h" + +namespace ARDOUR { + class Redirect; + class Curve; +} + +class GainAutomationTimeAxisView : public AutomationTimeAxisView +{ + public: + GainAutomationTimeAxisView (ARDOUR::Session&, + ARDOUR::Route&, + PublicEditor&, + TimeAxisView& parent_axis, + Gtk::Widget* parent, + std::string name, + ARDOUR::Curve&); + + ~GainAutomationTimeAxisView(); + + void add_automation_event (GtkCanvasItem *item, GdkEvent *event, jack_nframes_t, double); + + private: + ARDOUR::Curve& curve; + + void automation_changed (); + void set_automation_state (ARDOUR::AutoState); +}; + +#endif /* __ardour_gtk_gain_automation_time_axis_h__ */ diff --git a/gtk2_ardour/gain_meter.cc b/gtk2_ardour/gain_meter.cc new file mode 100644 index 0000000000..0e7f3b77aa --- /dev/null +++ b/gtk2_ardour/gain_meter.cc @@ -0,0 +1,762 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ardour_ui.h" +#include "gain_meter.h" +#include "utils.h" +#include "logmeter.h" +#include "gui_thread.h" + +#include +#include + +#include "i18n.h" +#include "misc_xpms" + +using namespace ARDOUR; +using namespace Gtkmmext; +using namespace Gtk; +using namespace SigC; + +Signal0 GainMeter::ResetAllPeakDisplays; +Signal1 GainMeter::ResetGroupPeakDisplays; +Pix* GainMeter::slider_pix = 0; + +int +GainMeter::setup_slider_pix () +{ + vector xpms; + + xpms.push_back (vslider_rail_xpm); + xpms.push_back (vslider_slider_xpm); + + if ((slider_pix = get_pix ("sliders", xpms, false)) == 0) { + error << _("Cannot create slider pixmaps") << endmsg; + return -1; + } + + slider_pix->ref (); + return 0; +} + +GainMeter::GainMeter (IO& io, Session& s) + : _io (io), + _session (s), + gain_slider (0), + // 0.781787 is the value needed for gain to be set to 0. + gain_adjustment (0.781787, 0.0, 1.0, 0.01, 0.1), + gain_display (&gain_adjustment, "MixerStripGainDisplay"), + gain_unit_label (_("dbFS")), + meter_point_label (_("pre")), + top_table (1, 2) + +{ + if (slider_pix == 0) { + setup_slider_pix (); + } + + ignore_toggle = false; + meter_menu = 0; + + gain_slider = manage (new VSliderController (slider_pix, + &gain_adjustment, + & _io.midi_gain_control(), + false)); + + gain_slider->button_press_event.connect (slot (*this, &GainMeter::start_gain_touch)); + gain_slider->button_release_event.connect (slot (*this, &GainMeter::end_gain_touch)); + gain_slider->set_name ("MixerGainMeter"); + + if (_session.midi_port()) { + _io.set_midi_to_gain_function (slider_position_to_gain); + _io.set_gain_to_midi_function (gain_to_slider_position); + } + + gain_display.set_print_func (_gain_printer, this); + set_usize_to_display_given_text (gain_display, "-86.0", 2, 2); + + gain_unit_button.add (gain_unit_label); + gain_unit_button.set_name ("MixerStripGainUnitButton"); + gain_unit_label.set_name ("MixerStripGainUnitButton"); + + top_table.set_col_spacings (2); + top_table.set_homogeneous (true); + top_table.attach (gain_unit_button, 0, 1, 0, 1); + + Route* r; + + if ((r = dynamic_cast (&_io)) != 0) { + r->meter_change.connect (slot (*this, &GainMeter::meter_changed)); + meter_point_button.add (meter_point_label); + meter_point_button.set_name ("MixerStripMeterPreButton"); + meter_point_label.set_name ("MixerStripMeterPreButton"); + + switch (r->meter_point()) { + case MeterInput: + meter_point_label.set_text (_("input")); + break; + + case MeterPreFader: + meter_point_label.set_text (_("pre")); + break; + + case MeterPostFader: + meter_point_label.set_text (_("post")); + break; + } + + /* TRANSLATORS: this string should be longest of the strings + used to describe meter points. In english, its "input". + */ + + set_usize_to_display_given_text (meter_point_button, _("tupni"), 2, 2); + + meter_point_button.button_press_event.connect (slot (*this, &GainMeter::meter_press)); + meter_point_button.button_release_event.connect (slot (*this, &GainMeter::meter_release)); + + top_table.attach (meter_point_button, 1, 2, 0, 1); + } + + gain_display_box.set_spacing (2); + gain_display_frame.set_shadow_type (GTK_SHADOW_IN); + gain_display_frame.set_name ("BaseFrame"); + gain_display_frame.add (gain_display); + gain_display_box.pack_start (gain_display_frame, false, false); + + peak_display.set_name ("MixerStripPeakDisplay"); + set_usize_to_display_given_text (peak_display, "-86.0", 2, 2); + peak_display.add (peak_display_label); + peak_display_frame.set_shadow_type (GTK_SHADOW_IN); + peak_display_frame.set_name ("BaseFrame"); + peak_display_frame.add (peak_display); + max_peak = minus_infinity(); + peak_display_label.set_text (_("-inf")); + + gain_display_box.pack_start (peak_display_frame, false, false); + + + meter_metric_area.set_usize (18, -1); + meter_metric_area.set_name ("MeterMetricsStrip"); + + meter_packer.show (); + gain_slider->show_all (); + + meter_packer.set_spacing (2); + fader_box.set_spacing (2); + + fader_box.pack_start (*gain_slider, false, false); + + hbox.set_spacing (4); + hbox.pack_start (fader_box, false, false); + hbox.pack_start (meter_packer, false, false); + + set_spacing (4); + pack_start (top_table, false, false); + pack_start (gain_display_box, false, false); + pack_start (hbox, false, false); + + show_all (); + + _io.gain_changed.connect (slot (*this, &GainMeter::gain_changed)); + + meter_metric_area.expose_event.connect (slot (*this, &GainMeter::meter_metrics_expose)); + gain_adjustment.value_changed.connect (slot (*this, &GainMeter::gain_adjusted)); + peak_display.button_release_event.connect (slot (*this, &GainMeter::peak_button_release)); + + _session.MeterHoldChanged.connect (slot (*this, &GainMeter::meter_hold_changed)); + + gain_changed (0); + update_gain_sensitive (); + + ResetAllPeakDisplays.connect (slot (*this, &GainMeter::reset_peak_display)); + ResetGroupPeakDisplays.connect (slot (*this, &GainMeter::reset_group_peak_display)); +} + +void +GainMeter::set_width (Width w) +{ + switch (w) { + case Wide: + peak_display_frame.show_all(); + break; + case Narrow: + peak_display_frame.hide_all(); + break; + } + + _width = w; + setup_meters (); +} + +gint +GainMeter::meter_metrics_expose (GdkEventExpose *ev) +{ + /* XXX optimize this so that it doesn't do it all everytime */ + + double fraction; + + Gdk_Window win (meter_metric_area.get_window()); + Gdk_GC fg_gc (meter_metric_area.get_style()->get_fg_gc (GTK_STATE_NORMAL)); + Gdk_GC bg_gc (meter_metric_area.get_style()->get_bg_gc (GTK_STATE_NORMAL)); + Gdk_Font font (meter_metric_area.get_style()->get_font()); + gint x, y, width, height, depth; + gint pos; + int db_points[] = { -50, -10, -3, 0, 6 }; + uint32_t i; + char buf[32]; + GdkRectangle base_rect; + GdkRectangle draw_rect; + + win.get_geometry (x, y, width, height, depth); + + base_rect.width = width; + base_rect.height = height; + base_rect.x = 0; + base_rect.y = 0; + + gdk_rectangle_intersect (&ev->area, &base_rect, &draw_rect); + win.draw_rectangle (bg_gc, true, draw_rect.x, draw_rect.y, draw_rect.width, draw_rect.height); + + for (i = 0; i < sizeof (db_points)/sizeof (db_points[0]); ++i) { + fraction = log_meter (db_points[i]); + pos = height - (gint) floor (height * fraction); + + snprintf (buf, sizeof (buf), "%d", db_points[i]); + + gint twidth; + gint lbearing; + gint rbearing; + gint ascent; + gint descent; + + gdk_string_extents (font, + buf, + &lbearing, + &rbearing, + &twidth, + &ascent, + &descent); + + win.draw_text (font, fg_gc, width - twidth, pos + ascent, buf, strlen (buf)); + } + + return TRUE; +} + +GainMeter::~GainMeter () +{ + + if (meter_menu) { + delete meter_menu; + } + + for (vector::iterator i = meters.begin(); i != meters.end(); i++) { + if ((*i).meter) { + delete (*i).meter; + } + } +} + +void +GainMeter::update_meters () +{ + vector::iterator i; + uint32_t n; + float peak; + char buf[32]; + + + for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) { + if ((*i).packed) { + peak = _io.peak_input_power (n); + + if (_session.meter_falloff() == 0.0f || peak > (*i).meter->get_user_level()) { + (*i).meter->set (log_meter (peak), peak); + } + + if (peak > max_peak) { + max_peak = peak; + /* set peak display */ + snprintf (buf, sizeof(buf), "%.1f", max_peak); + peak_display_label.set_text (buf); + + if (max_peak >= 0.0f) { + peak_display.set_name ("MixerStripPeakDisplayPeak"); + } + } + } + } + +} + +void +GainMeter::update_meters_falloff () +{ + vector::iterator i; + uint32_t n; + float dbpeak; + + for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) { + if ((*i).packed) { + // just do falloff + //peak = (*i).meter->get_level() * _falloff_rate; + dbpeak = (*i).meter->get_user_level() - _session.meter_falloff(); + + dbpeak = std::max(dbpeak, -200.0f); + + // cerr << "tmplevel: " << tmplevel << endl; + (*i).meter->set (log_meter (dbpeak), dbpeak); + } + } + +} + + +void +GainMeter::meter_hold_changed() +{ + ENSURE_GUI_THREAD(slot (*this, &GainMeter::meter_hold_changed)); + + vector::iterator i; + uint32_t n; + + for (n = 0, i = meters.begin(); i != meters.end(); ++i, ++n) { + + (*i).meter->set_hold_count ((uint32_t) floor(_session.meter_hold())); + } +} + +void +GainMeter::hide_all_meters () +{ + bool remove_metric_area = false; + + for (vector::iterator i = meters.begin(); i != meters.end(); ++i) { + if ((*i).packed) { + remove_metric_area = true; + meter_packer.remove (*((*i).meter)); + (*i).packed = false; + } + } + + if (remove_metric_area) { + if (meter_metric_area.get_parent()) { + meter_packer.remove (meter_metric_area); + } + } +} + +void +GainMeter::setup_meters () +{ + uint32_t nmeters = _io.n_outputs(); + guint16 width; + + hide_all_meters (); + + Route* r; + + if ((r = dynamic_cast (&_io)) != 0) { + + switch (r->meter_point()) { + case MeterPreFader: + case MeterInput: + nmeters = r->n_inputs(); + break; + case MeterPostFader: + nmeters = r->n_outputs(); + break; + } + + } else { + + nmeters = _io.n_outputs(); + + } + + if (nmeters == 0) { + return; + } + + if (_width == Wide) { + meter_packer.pack_start (meter_metric_area, false, false); + meter_metric_area.show_all (); + } + + if (nmeters <= 2) { + width = regular_meter_width; + } else { + width = thin_meter_width; + } + + while (meters.size() < nmeters) { + meters.push_back (MeterInfo()); + } + + for (uint32_t n = 0; n < nmeters; ++n) { + if (meters[n].width != width) { + delete meters[n].meter; + meters[n].meter = new FastMeter ((uint32_t) floor (_session.meter_hold()), width, FastMeter::Vertical); + meters[n].width = width; + + meters[n].meter->add_events (GDK_BUTTON_RELEASE_MASK); + meters[n].meter->button_release_event.connect + (bind (slot (*this, &GainMeter::meter_button_release), n)); + meters[n].meter->button_release_event.connect_after (slot (do_not_propagate)); + } + + meter_packer.pack_start (*meters[n].meter, false, false); + meters[n].meter->show_all (); + meters[n].packed = true; + } +} + +gint +GainMeter::peak_button_release (GdkEventButton* ev) +{ + /* reset peak label */ + + if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control|Keyboard::Shift)) { + ResetAllPeakDisplays (); + } else if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + Route* r; + if ((r = dynamic_cast (&_io)) != 0) { + ResetGroupPeakDisplays (r->mix_group()); + } + } else { + reset_peak_display (); + } + return TRUE; +} + +void +GainMeter::reset_peak_display () +{ + max_peak = minus_infinity(); + peak_display_label.set_text (_("-inf")); + peak_display.set_name ("MixerStripPeakDisplay"); +} + +void +GainMeter::reset_group_peak_display (RouteGroup* group) +{ + Route* r; + if ((r = dynamic_cast (&_io)) != 0) { + if (group == r->mix_group()) { + reset_peak_display (); + } + } +} + +gint +GainMeter::meter_button_release (GdkEventButton* ev, uint32_t which) +{ + switch (ev->button) { + case 1: + meters[which].meter->clear(); + max_peak = minus_infinity(); + peak_display_label.set_text (_("-inf")); + peak_display.set_name ("MixerStripPeakDisplay"); + break; + + case 3: + // popup_meter_menu (ev); + break; + }; + + return TRUE; +} + +void +GainMeter::popup_meter_menu (GdkEventButton *ev) +{ + using namespace Menu_Helpers; + + if (meter_menu == 0) { + meter_menu = new Gtk::Menu; + MenuList& items = meter_menu->items(); + + items.push_back (MenuElem ("-inf .. +0dBFS")); + items.push_back (MenuElem ("-10dB .. +0dBFS")); + items.push_back (MenuElem ("-4 .. +0dBFS")); + items.push_back (SeparatorElem()); + items.push_back (MenuElem ("-inf .. -2dBFS")); + items.push_back (MenuElem ("-10dB .. -2dBFS")); + items.push_back (MenuElem ("-4 .. -2dBFS")); + } + + meter_menu->popup (1, ev->time); +} + +void +GainMeter::_gain_printer (char buf[32], Gtk::Adjustment& adj, void *arg) +{ + static_cast(arg)->gain_printer (buf, adj); +} + +void +GainMeter::gain_printer (char buf[32], Gtk::Adjustment& adj) +{ + float v = adj.get_value(); + + if (v == 0.0) { + strcpy (buf, _("-inf")); + } else { + snprintf (buf, 32, "%.1f", coefficient_to_dB (slider_position_to_gain (v))); + } +} + +void +GainMeter::gain_adjusted () +{ + if (!ignore_toggle) { + _io.set_gain (slider_position_to_gain (gain_adjustment.get_value()), this); + } +} + +void +GainMeter::effective_gain_display () +{ + gfloat value = gain_to_slider_position (_io.effective_gain()); + + if (gain_adjustment.get_value() != value) { + ignore_toggle = true; + gain_adjustment.set_value (value); + ignore_toggle = false; + } +} + +void +GainMeter::gain_changed (void *src) +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &GainMeter::effective_gain_display)); +} + +gint +GainMeter::entry_focus_event (GdkEventFocus* ev) +{ + if (ev->in) { + ARDOUR_UI::instance()->allow_focus (true); + } else { + ARDOUR_UI::instance()->allow_focus (false); + } + return TRUE; +} + + +void +GainMeter::set_meter_strip_name (string name) +{ + meter_metric_area.set_name (name); +} + +void +GainMeter::set_fader_name (string name) +{ + gain_slider->set_name (name); +} + +void +GainMeter::update_gain_sensitive () +{ + static_cast(gain_slider)->set_sensitive (!(_io.gain_automation_state() & Play)); +} + + +static MeterPoint +next_meter_point (MeterPoint mp) +{ + switch (mp) { + case MeterInput: + return MeterPreFader; + break; + + case MeterPreFader: + return MeterPostFader; + break; + + case MeterPostFader: + return MeterInput; + break; + } + /*NOTREACHED*/ + return MeterInput; +} + +gint +GainMeter::meter_press(GdkEventButton* ev) +{ + Route* _route; + + wait_for_release = false; + + if ((_route = dynamic_cast(&_io)) == 0) { + return FALSE; + } + + if (!ignore_toggle) { + + if (Keyboard::is_context_menu_event (ev)) { + + // no menu at this time. + + } else { + + if (ev->button == 2) { + + // ctrl-button2 click is the midi binding click + // button2-click is "momentary" + + if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) { + wait_for_release = true; + old_meter_point = _route->meter_point (); + } + } + + if (ev->button == 1 || ev->button == 2) { + + if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) { + + /* ctrl-shift-click applies change to all routes */ + + _session.foreach_route (this, &GainMeter::set_meter_point, next_meter_point (_route->meter_point())); + + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + + /* ctrl-click: solo mix group. + ctrl-button2 is MIDI learn. + */ + + if (ev->button == 1) { + set_mix_group_meter_point (*_route, next_meter_point (_route->meter_point())); + } + + } else { + + /* click: solo this route */ + + _route->set_meter_point (next_meter_point (_route->meter_point()), this); + } + } + } + } + + return stop_signal (meter_point_button, "button-press-event"); + +} + +gint +GainMeter::meter_release(GdkEventButton* ev) +{ + if(!ignore_toggle){ + if (wait_for_release){ + wait_for_release = false; + set_meter_point (*(dynamic_cast(&_io)), old_meter_point); + stop_signal (meter_point_button, "button-release-event"); + } + } + return TRUE; +} + +void +GainMeter::set_meter_point (Route& route, MeterPoint mp) +{ + route.set_meter_point (mp, this); +} + +void +GainMeter::set_mix_group_meter_point (Route& route, MeterPoint mp) +{ + RouteGroup* mix_group; + + if((mix_group = route.mix_group()) != 0){ + mix_group->apply (&Route::set_meter_point, mp, this); + } else { + route.set_meter_point (mp, this); + } +} + +void +GainMeter::meter_changed (void *src) +{ + Route* r; + + ENSURE_GUI_THREAD (bind (slot (*this, &GainMeter::meter_changed), src)); + + if ((r = dynamic_cast (&_io)) != 0) { + + switch (r->meter_point()) { + case MeterInput: + meter_point_label.set_text (_("input")); + break; + + case MeterPreFader: + meter_point_label.set_text (_("pre")); + break; + + case MeterPostFader: + meter_point_label.set_text (_("post")); + break; + } + + setup_meters (); + } +} + +void +GainMeter::meter_point_clicked () +{ + Route* r; + + if ((r = dynamic_cast (&_io)) != 0) { + + } +} + +gint +GainMeter::start_gain_touch (GdkEventButton* ev) +{ + _io.start_gain_touch (); + return FALSE; +} + +gint +GainMeter::end_gain_touch (GdkEventButton* ev) +{ + _io.end_gain_touch (); + return FALSE; +} diff --git a/gtk2_ardour/gain_meter.h b/gtk2_ardour/gain_meter.h new file mode 100644 index 0000000000..06ae0dafd9 --- /dev/null +++ b/gtk2_ardour/gain_meter.h @@ -0,0 +1,156 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_gain_meter_h__ +#define __ardour_gtk_gain_meter_h__ + +#include + +#include + +#include +#include +#include + +#include "enums.h" + +namespace ARDOUR { + class IO; + class Session; + class Route; + class RouteGroup; +} +namespace Gtkmmext { + class FastMeter; + class BarController; + class Pix; +} + +class GainMeter : public Gtk::VBox +{ + public: + GainMeter (ARDOUR::IO&, ARDOUR::Session&); + ~GainMeter (); + + void update_gain_sensitive (); + + void update_meters (); + void update_meters_falloff (); + + void effective_gain_display (); + + void set_width (Width); + void setup_meters (); + + void set_meter_strip_name (string name); + void set_fader_name (string name); + + private: + ARDOUR::IO& _io; + ARDOUR::Session& _session; + + bool ignore_toggle; + + Gtkmmext::VSliderController *gain_slider; + Gtk::Adjustment gain_adjustment; + Gtk::Frame gain_display_frame; + Gtkmmext::ClickBox gain_display; + Gtk::Frame peak_display_frame; + Gtk::EventBox peak_display; + Gtk::Label peak_display_label; + Gtk::Button gain_unit_button; + Gtk::Label gain_unit_label; + Gtk::HBox gain_display_box; + Gtk::HBox fader_box; + Gtk::DrawingArea meter_metric_area; + Gtk::Button meter_point_button; + Gtk::Label meter_point_label; + Gtk::Table top_table; + Width _width; + + gint meter_metrics_expose (GdkEventExpose *); + + static void _gain_printer (char buf[32], Gtk::Adjustment&, void *); + void gain_printer (char buf[32], Gtk::Adjustment&); + + struct MeterInfo { + Gtkmmext::FastMeter *meter; + gint16 width; + bool packed; + + MeterInfo() { + meter = 0; + width = 0; + packed = false; + } + }; + + static const guint16 regular_meter_width = 5; + static const guint16 thin_meter_width = 2; + vector meters; + float max_peak; + + + Gtk::HBox hbox; + Gtk::HBox meter_packer; + + void gain_adjusted (); + void gain_changed (void *); + + void meter_point_clicked (); + void meter_changed (void *); + void gain_unit_changed (); + + void hide_all_meters (); + + gint meter_button_press (GdkEventButton*, uint32_t); + gint meter_button_release (GdkEventButton*, uint32_t); + + gint peak_button_release (GdkEventButton*); + + Gtk::Menu* meter_menu; + void popup_meter_menu (GdkEventButton*); + + gint start_gain_touch (GdkEventButton*); + gint end_gain_touch (GdkEventButton*); + + gint entry_focus_event (GdkEventFocus* ev); + + void set_mix_group_meter_point (ARDOUR::Route&, ARDOUR::MeterPoint); + void set_meter_point (ARDOUR::Route&, ARDOUR::MeterPoint); + gint meter_release (GdkEventButton*); + gint meter_press (GdkEventButton*); + bool wait_for_release; + ARDOUR::MeterPoint old_meter_point; + + void meter_hold_changed(); + + void reset_peak_display (); + void reset_group_peak_display (ARDOUR::RouteGroup*); + + static SigC::Signal0 ResetAllPeakDisplays; + static SigC::Signal1 ResetGroupPeakDisplays; + + static Gtkmmext::Pix* slider_pix; + static int setup_slider_pix (); +}; + +#endif /* __ardour_gtk_gain_meter_h__ */ + diff --git a/gtk2_ardour/gettext.h b/gtk2_ardour/gettext.h new file mode 100644 index 0000000000..339c74ffe7 --- /dev/null +++ b/gtk2_ardour/gettext.h @@ -0,0 +1,82 @@ +/* Convenience header for conditional use of GNU . + Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option. */ +#if ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +# include + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of a NOP. We don't include + as well because people using "gettext.h" will not include , + and also including would fail on SunOS 4, whereas + is OK. */ +#if defined(__sun) +# include +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ + +/* other headers may have included libintl.h */ + +# undef gettext +# undef dgettext +# undef dcgettext +# undef ngettext +# undef dngettext +# undef dcngettext +# undef textdomain +# undef bindtextdomain +# undef bind_textdomain_codeset + +# define gettext(Msgid) ((const char *) (Msgid)) +# define dgettext(Domainname, Msgid) ((const char *) (Msgid)) +# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define textdomain(Domainname) ((const char *) (Domainname)) +# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) +# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) + +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +#endif /* _LIBGETTEXT_H */ diff --git a/gtk2_ardour/ghostregion.cc b/gtk2_ardour/ghostregion.cc new file mode 100644 index 0000000000..8caacac3b3 --- /dev/null +++ b/gtk2_ardour/ghostregion.cc @@ -0,0 +1,68 @@ +#include "canvas-simplerect.h" +#include "ghostregion.h" +#include "automation_time_axis.h" +#include "rgb_macros.h" + +using namespace Editing; + +GhostRegion::GhostRegion (AutomationTimeAxisView& atv, double initial_pos) + : trackview (atv) +{ + group = gtk_canvas_item_new (GTK_CANVAS_GROUP(trackview.canvas_display), + gtk_canvas_group_get_type(), + "x", initial_pos, + "y", 0.0, + NULL); + + base_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_simplerect_get_type(), + "x1", (double) 0.0, + "y1", (double) 0.0, + "y2", (double) trackview.height, + "outline_what", (guint32) 0, + "outline_color_rgba", color_map[cGhostTrackBaseOutline], + "fill_color_rgba", color_map[cGhostTrackBaseFill], + NULL); + + gtk_canvas_item_lower_to_bottom (group); + + atv.add_ghost (this); +} + +GhostRegion::~GhostRegion () +{ + GoingAway (this); + gtk_object_destroy (GTK_OBJECT(group)); +} + +void +GhostRegion::set_samples_per_unit (double spu) +{ + for (vector::iterator i = waves.begin(); i != waves.end(); ++i) { + gtk_canvas_item_set ((*i), "samples_per_unit", spu, NULL); + } +} + +void +GhostRegion::set_duration (double units) +{ + gtk_canvas_item_set (base_rect, "x2", units, NULL); +} + +void +GhostRegion::set_height () +{ + gdouble ht; + vector::iterator i; + uint32_t n; + + gtk_canvas_item_set (base_rect, "y2", (double) trackview.height, NULL); + + ht = ((trackview.height) / (double) waves.size()); + + for (n = 0, i = waves.begin(); i != waves.end(); ++i, ++n) { + gdouble yoff = n * ht; + gtk_canvas_item_set ((*i), "height", ht, "y", yoff, NULL); + } +} + diff --git a/gtk2_ardour/ghostregion.h b/gtk2_ardour/ghostregion.h new file mode 100644 index 0000000000..0abb1b9b91 --- /dev/null +++ b/gtk2_ardour/ghostregion.h @@ -0,0 +1,47 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_ghost_region_h__ +#define __ardour_gtk_ghost_region_h__ + +#include +#include +#include + +class AutomationTimeAxisView; + +struct GhostRegion : public SigC::Object +{ + AutomationTimeAxisView& trackview; + GtkCanvasItem* group; + GtkCanvasItem* base_rect; + std::vector waves; + + GhostRegion (AutomationTimeAxisView& tv, double initial_unit_pos); + ~GhostRegion (); + + void set_samples_per_unit (double spu); + void set_duration (double units); + void set_height (); + + SigC::Signal1 GoingAway; +}; + +#endif /* __ardour_gtk_ghost_region_h__ */ diff --git a/gtk2_ardour/gprofhelper.c b/gtk2_ardour/gprofhelper.c new file mode 100644 index 0000000000..b806a073c6 --- /dev/null +++ b/gtk2_ardour/gprofhelper.c @@ -0,0 +1,117 @@ +/* gprof-helper.c -- preload library to profile pthread-enabled programs + * + * Authors: Sam Hocevar + * Daniel Jönsson + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Do What The Fuck You Want To + * Public License as published by Banlu Kemiyatorn. See + * http://sam.zoy.org/projects/COPYING.WTFPL for more details. + * + * Compilation example: + * gcc -shared -nostdlib -fPIC gprof-helper.c -o gprof-helper.so -lpthread -ldl + * + * Usage example: + * LD_PRELOAD=./gprof-helper.so your_program + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +static void * wrapper_routine(void *); + +/* Original pthread function */ +static int (*pthread_create_orig)(pthread_t *__restrict, + __const pthread_attr_t *__restrict, + void *(*)(void *), + void *__restrict) = NULL; + +/* Library initialization function */ +void _init(void) +{ + pthread_create_orig = dlsym(RTLD_NEXT, "pthread_create"); + fprintf(stderr, "pthreads: using profiling hooks for gprof\n"); + if(pthread_create_orig == NULL) + { + char *error = dlerror(); + if(error == NULL) + { + error = "pthread_create is NULL"; + } + fprintf(stderr, "%s", error); + exit(EXIT_FAILURE); + } +} + +/* Our data structure passed to the wrapper */ +typedef struct wrapper_s +{ + void * (*start_routine)(void *); + void * arg; + + pthread_mutex_t lock; + pthread_cond_t wait; + + struct itimerval itimer; + +} wrapper_t; + +/* The wrapper function in charge for setting the itimer value */ +static void * wrapper_routine(void * data) +{ + /* Put user data in thread-local variables */ + void * (*start_routine)(void *) = ((wrapper_t*)data)->start_routine; + void * arg = ((wrapper_t*)data)->arg; + + /* Set the profile timer value */ + setitimer(ITIMER_PROF, &((wrapper_t*)data)->itimer, NULL); + + /* Tell the calling thread that we don't need its data anymore */ + pthread_mutex_lock(&((wrapper_t*)data)->lock); + pthread_cond_signal(&((wrapper_t*)data)->wait); + pthread_mutex_unlock(&((wrapper_t*)data)->lock); + + /* Call the real function */ + return start_routine(arg); +} + +/* Our wrapper function for the real pthread_create() */ +int pthread_create(pthread_t *__restrict thread, + __const pthread_attr_t *__restrict attr, + void * (*start_routine)(void *), + void *__restrict arg) +{ + wrapper_t wrapper_data; + int i_return; + + /* Initialize the wrapper structure */ + wrapper_data.start_routine = start_routine; + wrapper_data.arg = arg; + getitimer(ITIMER_PROF, &wrapper_data.itimer); + pthread_cond_init(&wrapper_data.wait, NULL); + pthread_mutex_init(&wrapper_data.lock, NULL); + pthread_mutex_lock(&wrapper_data.lock); + + /* The real pthread_create call */ + i_return = pthread_create_orig(thread, + attr, + &wrapper_routine, + &wrapper_data); + + /* If the thread was successfully spawned, wait for the data + * to be released */ + if(i_return == 0) + { + pthread_cond_wait(&wrapper_data.wait, &wrapper_data.lock); + } + + pthread_mutex_unlock(&wrapper_data.lock); + pthread_mutex_destroy(&wrapper_data.lock); + pthread_cond_destroy(&wrapper_data.wait); + + return i_return; +} diff --git a/gtk2_ardour/grouped_buttons.cc b/gtk2_ardour/grouped_buttons.cc new file mode 100644 index 0000000000..544b3e1ed8 --- /dev/null +++ b/gtk2_ardour/grouped_buttons.cc @@ -0,0 +1,96 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include "grouped_buttons.h" + +using namespace std; + +GroupedButtons::GroupedButtons (vector& buttonset) +{ + uint32_t n = 0; + + buttons = buttonset; + + for (vector::iterator i = buttons.begin(); i != buttons.end(); ++i, ++n) { + if ((*i)->get_active()) { + current_active = n; + } + (*i)->clicked.connect (bind (slot (*this, &GroupedButtons::one_clicked), n)); + } +} + +GroupedButtons::GroupedButtons (uint32_t nbuttons, uint32_t first_active) +{ + buttons.reserve (nbuttons); + current_active = first_active; + + for (uint32_t n = 0; n < nbuttons; ++n) { + + Gtk::ToggleButton *button; + + button = manage (new (Gtk::ToggleButton)); + + if (n == current_active) { + button->set_active (true); + } + + button->clicked.connect (bind (slot (*this, &GroupedButtons::one_clicked), n)); + buttons.push_back (button); + } +} + +static gint +reactivate_button (void *arg) +{ + Gtk::ToggleButton *b = (Gtk::ToggleButton *) arg; + b->set_active (true); + return FALSE; +} + +void +GroupedButtons::one_clicked (uint32_t which) +{ + if (buttons[which]->get_active()) { + + if (which != current_active) { + uint32_t old = current_active; + current_active = which; + buttons[old]->set_active (false); + } + + } else if (which == current_active) { + + /* Someobody tried to unset the current active + button by clicking on it. This caused + set_active (false) to be called. We don't + allow that, so just reactivate it. + + Don't try this right here, because of some + design glitches with GTK+ toggle buttons. + Setting the button back to active from + within the signal emission that marked + it as inactive causes a segfault ... + */ + + gtk_idle_add (reactivate_button, buttons[which]); + } +} diff --git a/gtk2_ardour/grouped_buttons.h b/gtk2_ardour/grouped_buttons.h new file mode 100644 index 0000000000..ff8051a120 --- /dev/null +++ b/gtk2_ardour/grouped_buttons.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __gtkmmext_grouped_buttons_h__ +#define __gtkmmext_grouped_buttons_h__ + +#include + +#include +#include + +namespace Gtk { + class ToggleButton; +}; + +class GroupedButtons : public SigC::Object +{ + public: + GroupedButtons (uint32_t nbuttons, uint32_t first_active); + GroupedButtons (std::vector&); + + Gtk::ToggleButton& button (uint32_t which) { + return *buttons[which]; + } + + private: + std::vector buttons; + uint32_t current_active; + void one_clicked (uint32_t which); +}; + +#endif /* __gtkmmext_grouped_buttons_h__ */ diff --git a/gtk2_ardour/gtk-custom-hruler.c b/gtk2_ardour/gtk-custom-hruler.c new file mode 100644 index 0000000000..d028d6472e --- /dev/null +++ b/gtk2_ardour/gtk-custom-hruler.c @@ -0,0 +1,239 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* modified by andreas meyer */ +/* subsequently specialized for audio time displays by paul davis */ + +#include +#include +#include +#include "gtk-custom-hruler.h" + +#define RULER_HEIGHT 14 +#define MINIMUM_INCR 5 +#define MAXIMUM_SUBDIVIDE 5 + +#define ROUND(x) ((int) ((x) + 0.5)) + +static void gtk_custom_hruler_class_init (GtkCustomHRulerClass * klass); +static void gtk_custom_hruler_init (GtkCustomHRuler * custom_hruler); +static gint gtk_custom_hruler_motion_notify (GtkWidget * widget, GdkEventMotion * event); +static void gtk_custom_hruler_draw_ticks (GtkCustomRuler * ruler); +static void gtk_custom_hruler_draw_pos (GtkCustomRuler * ruler); + +guint gtk_custom_hruler_get_type (void) +{ + static guint custom_hruler_type = 0; + + if (!custom_hruler_type) { + static const GtkTypeInfo custom_hruler_info = { + "GtkCustomHRuler", + sizeof (GtkCustomHRuler), + sizeof (GtkCustomHRulerClass), + (GtkClassInitFunc) gtk_custom_hruler_class_init, + (GtkObjectInitFunc) gtk_custom_hruler_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + custom_hruler_type = gtk_type_unique (gtk_custom_ruler_get_type (), &custom_hruler_info); + } + return custom_hruler_type; +} + +static void +gtk_custom_hruler_class_init (GtkCustomHRulerClass * klass) +{ + GtkWidgetClass *widget_class; + GtkCustomRulerClass *ruler_class; + + widget_class = (GtkWidgetClass *) klass; + ruler_class = (GtkCustomRulerClass *) klass; + + widget_class->motion_notify_event = gtk_custom_hruler_motion_notify; + + ruler_class->draw_ticks = gtk_custom_hruler_draw_ticks; + ruler_class->draw_pos = gtk_custom_hruler_draw_pos; +} + +static void +gtk_custom_hruler_init (GtkCustomHRuler * custom_hruler) +{ + GtkWidget *widget; + + widget = GTK_WIDGET (custom_hruler); + widget->requisition.width = widget->style->klass->xthickness * 2 + 1; + widget->requisition.height = widget->style->klass->ythickness * 2 + RULER_HEIGHT; +} + + +GtkWidget * +gtk_custom_hruler_new (void) +{ + return GTK_WIDGET (gtk_type_new (gtk_custom_hruler_get_type ())); +} + +static gint +gtk_custom_hruler_motion_notify (GtkWidget * widget, GdkEventMotion * event) +{ + GtkCustomRuler *ruler; + gint x; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_CUSTOM_HRULER (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + ruler = GTK_CUSTOM_RULER (widget); + + if (event->is_hint) + gdk_window_get_pointer (widget->window, &x, NULL, NULL); + else + x = event->x; + + ruler->position = ruler->lower + ((ruler->upper - ruler->lower) * x) / widget->allocation.width; + + /* Make sure the ruler has been allocated already */ + if (ruler->backing_store != NULL) + gtk_custom_ruler_draw_pos (ruler); + + return FALSE; +} + +static void +gtk_custom_hruler_draw_ticks (GtkCustomRuler * ruler) +{ + GtkWidget *widget; + GdkGC *gc, *bg_gc; + GdkFont *font; + gint i; + GtkCustomRulerMark *marks; + gint nmarks; + gint max_chars; + + g_return_if_fail (ruler != NULL); + g_return_if_fail (GTK_IS_CUSTOM_HRULER (ruler)); + + if (!GTK_WIDGET_DRAWABLE (ruler)) + return; + + widget = GTK_WIDGET (ruler); + + gc = widget->style->fg_gc[GTK_STATE_NORMAL]; + bg_gc = widget->style->bg_gc[GTK_STATE_NORMAL]; + font = widget->style->font; + + gtk_paint_box (widget->style, ruler->backing_store, + GTK_STATE_NORMAL, GTK_SHADOW_NONE, + NULL, widget, "custom_hruler", 0, 0, widget->allocation.width, widget->allocation.height); + + gdk_draw_line (ruler->backing_store, gc, 0, widget->allocation.height - 1, + widget->allocation.width, widget->allocation.height - 1); + + if ((ruler->upper - ruler->lower) == 0) { + return; + } + + /* we have to assume a fixed width font here */ + + max_chars = widget->allocation.width / gdk_string_width (font, "8"); + + nmarks = ruler->metric->get_marks (&marks, ruler->lower, ruler->upper, max_chars); + + for (i = 0; i < nmarks; i++) { + gint pos; + gint height; + + pos = ROUND ((marks[i].position - ruler->lower) / ruler->metric->units_per_pixel); + height = widget->allocation.height; + + switch (marks[i].style) { + case GtkCustomRulerMarkMajor: + gdk_draw_line (ruler->backing_store, gc, pos, height, pos, 0); + break; + case GtkCustomRulerMarkMinor: + gdk_draw_line (ruler->backing_store, gc, pos, height, pos, height - (height/2)); + break; + case GtkCustomRulerMarkMicro: + gdk_draw_line (ruler->backing_store, gc, pos, height, pos, height - 3); + break; + } + + gdk_draw_string (ruler->backing_store, font, gc, pos + 2, font->ascent - 1, marks[i].label); + g_free (marks[i].label); + } + + if (nmarks) { + g_free (marks); + } +} + +static void +gtk_custom_hruler_draw_pos (GtkCustomRuler * ruler) +{ + GtkWidget *widget; + GdkGC *gc; + int i; + gint x, y; + gint width, height; + gint bs_width, bs_height; + gint xthickness; + gint ythickness; + gfloat increment; + + g_return_if_fail (ruler != NULL); + g_return_if_fail (GTK_IS_CUSTOM_HRULER (ruler)); + if (GTK_WIDGET_DRAWABLE (ruler) && (ruler->upper - ruler->lower) > 0) { + widget = GTK_WIDGET (ruler); + gc = widget->style->fg_gc[GTK_STATE_NORMAL]; + xthickness = widget->style->klass->xthickness; + ythickness = widget->style->klass->ythickness; + width = widget->allocation.width; + height = widget->allocation.height - ythickness * 2; + + bs_width = height / 2; + bs_width |= 1; /* make sure it's odd */ + bs_height = bs_width / 2 + 1; + + if ((bs_width > 0) && (bs_height > 0)) { + /* If a backing store exists, restore the ruler */ + if (ruler->backing_store && ruler->non_gr_exp_gc) + gdk_draw_pixmap (ruler->widget.window, + ruler->non_gr_exp_gc, + ruler->backing_store, ruler->xsrc, ruler->ysrc, ruler->xsrc, ruler->ysrc, bs_width, bs_height); + + increment = (gfloat) width / (ruler->upper - ruler->lower); + x = ROUND ((ruler->position - ruler->lower) * increment) + (xthickness - bs_width) / 2 - 1; + y = (height + bs_height) / 2 + ythickness; + + for (i = 0; i < bs_height; i++) + gdk_draw_line (widget->window, gc, x + i, y + i, x + bs_width - 1 - i, y + i); + + + ruler->xsrc = x; + ruler->ysrc = y; + } + } +} diff --git a/gtk2_ardour/gtk-custom-hruler.h b/gtk2_ardour/gtk-custom-hruler.h new file mode 100644 index 0000000000..a8c3affeb1 --- /dev/null +++ b/gtk2_ardour/gtk-custom-hruler.h @@ -0,0 +1,70 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* modified by andreas meyer */ + +#ifndef __GTK_CUSTOM_HRULER_H__ +#define __GTK_CUSTOM_HRULER_H__ + + +#include +#include "gtk-custom-ruler.h" + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define GTK_CUSTOM_HRULER(obj) GTK_CHECK_CAST (obj, gtk_custom_hruler_get_type (), GtkCustomHRuler) +#define GTK_CUSTOM_HRULER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_custom_hruler_get_type (), GtkCustomHRulerClass) +#define GTK_IS_CUSTOM_HRULER(obj) GTK_CHECK_TYPE (obj, gtk_custom_hruler_get_type ()) + + +typedef struct _GtkCustomHRuler GtkCustomHRuler; +typedef struct _GtkCustomHRulerClass GtkCustomHRulerClass; + +struct _GtkCustomHRuler +{ + GtkCustomRuler ruler; +}; + +struct _GtkCustomHRulerClass +{ + GtkCustomRulerClass parent_class; +}; + + +guint gtk_custom_hruler_get_type (void); +GtkWidget* gtk_custom_hruler_new (void); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GTK_CUSTOM_HRULER_H__ */ diff --git a/gtk2_ardour/gtk-custom-ruler.c b/gtk2_ardour/gtk-custom-ruler.c new file mode 100644 index 0000000000..8f63f82f01 --- /dev/null +++ b/gtk2_ardour/gtk-custom-ruler.c @@ -0,0 +1,367 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* modified by andreas meyer */ + +#include +#include "gtk-custom-ruler.h" + +enum +{ + ARG_0, + ARG_LOWER, + ARG_UPPER, + ARG_POSITION, + ARG_MAX_SIZE, + ARG_SHOW_POSITION +}; + +static void gtk_custom_ruler_class_init (GtkCustomRulerClass * klass); +static void gtk_custom_ruler_init (GtkCustomRuler * ruler); +static void gtk_custom_ruler_realize (GtkWidget * widget); +static void gtk_custom_ruler_unrealize (GtkWidget * widget); +static void gtk_custom_ruler_size_allocate (GtkWidget * widget, GtkAllocation * allocation); +static gint gtk_custom_ruler_expose (GtkWidget * widget, GdkEventExpose * event); +static void gtk_custom_ruler_make_pixmap (GtkCustomRuler * ruler); +static void gtk_custom_ruler_set_arg (GtkObject * object, GtkArg * arg, guint arg_id); +static void gtk_custom_ruler_get_arg (GtkObject * object, GtkArg * arg, guint arg_id); + +static gint +default_metric_get_marks (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars) +{ + return 0; +} + +static const GtkCustomMetric default_metric = { + 1.0, + default_metric_get_marks +}; + +static GtkWidgetClass *parent_class; + +GtkType gtk_custom_ruler_get_type (void) +{ + static GtkType ruler_type = 0; + + if (!ruler_type) { + static const GtkTypeInfo ruler_info = { + "GtkCustomRuler", + sizeof (GtkCustomRuler), + sizeof (GtkCustomRulerClass), + (GtkClassInitFunc) gtk_custom_ruler_class_init, + (GtkObjectInitFunc) gtk_custom_ruler_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + ruler_type = gtk_type_unique (GTK_TYPE_WIDGET, &ruler_info); + } + return ruler_type; +} + +static void +gtk_custom_ruler_class_init (GtkCustomRulerClass * class) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + object_class = (GtkObjectClass *) class; + widget_class = (GtkWidgetClass *) class; + + parent_class = gtk_type_class (GTK_TYPE_WIDGET); + + object_class->set_arg = gtk_custom_ruler_set_arg; + object_class->get_arg = gtk_custom_ruler_get_arg; + + widget_class->realize = gtk_custom_ruler_realize; + widget_class->unrealize = gtk_custom_ruler_unrealize; + widget_class->size_allocate = gtk_custom_ruler_size_allocate; + widget_class->expose_event = gtk_custom_ruler_expose; + + class->draw_ticks = NULL; + class->draw_pos = NULL; + + gtk_object_add_arg_type ("GtkCustomRuler::lower", GTK_TYPE_ULONG, GTK_ARG_READWRITE, ARG_LOWER); + gtk_object_add_arg_type ("GtkCustomRuler::upper", GTK_TYPE_ULONG, GTK_ARG_READWRITE, ARG_UPPER); + gtk_object_add_arg_type ("GtkCustomRuler::position", GTK_TYPE_ULONG, GTK_ARG_READWRITE, ARG_POSITION); + gtk_object_add_arg_type ("GtkCustomRuler::max_size", GTK_TYPE_ULONG, GTK_ARG_READWRITE, ARG_MAX_SIZE); + gtk_object_add_arg_type ("GtkCustomRuler::show_position", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_POSITION); +} + +static void +gtk_custom_ruler_init (GtkCustomRuler * ruler) +{ + ruler->backing_store = NULL; + ruler->non_gr_exp_gc = NULL; + ruler->xsrc = 0; + ruler->ysrc = 0; + ruler->slider_size = 0; + ruler->lower = 0; + ruler->upper = 0; + ruler->position = 0; + ruler->max_size = 0; + ruler->show_position = FALSE; + + gtk_custom_ruler_set_metric (ruler, NULL); +} + +static void +gtk_custom_ruler_set_arg (GtkObject * object, GtkArg * arg, guint arg_id) +{ + GtkCustomRuler *ruler = GTK_CUSTOM_RULER (object); + + switch (arg_id) { + case ARG_LOWER: + gtk_custom_ruler_set_range (ruler, GTK_VALUE_ULONG (*arg), ruler->upper, ruler->position, ruler->max_size); + break; + case ARG_UPPER: + gtk_custom_ruler_set_range (ruler, ruler->lower, GTK_VALUE_ULONG (*arg), ruler->position, ruler->max_size); + break; + case ARG_POSITION: + gtk_custom_ruler_set_range (ruler, ruler->lower, ruler->upper, GTK_VALUE_ULONG (*arg), ruler->max_size); + break; + case ARG_MAX_SIZE: + gtk_custom_ruler_set_range (ruler, ruler->lower, ruler->upper, ruler->position, GTK_VALUE_ULONG (*arg)); + break; + case ARG_SHOW_POSITION: + // gtk_customer_ruler_set_show_position (ruler, GTK_VALUE_BOOL (*arg)); + break; + } +} + +static void +gtk_custom_ruler_get_arg (GtkObject * object, GtkArg * arg, guint arg_id) +{ + GtkCustomRuler *ruler = GTK_CUSTOM_RULER (object); + + switch (arg_id) { + case ARG_LOWER: + GTK_VALUE_ULONG (*arg) = ruler->lower; + break; + case ARG_UPPER: + GTK_VALUE_ULONG (*arg) = ruler->upper; + break; + case ARG_POSITION: + GTK_VALUE_ULONG (*arg) = ruler->position; + break; + case ARG_MAX_SIZE: + GTK_VALUE_ULONG (*arg) = ruler->max_size; + break; + case ARG_SHOW_POSITION: + GTK_VALUE_BOOL (*arg) = ruler->show_position; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +void +gtk_custom_ruler_set_metric (GtkCustomRuler * ruler, GtkCustomMetric * metric) +{ + g_return_if_fail (ruler != NULL); + g_return_if_fail (GTK_IS_CUSTOM_RULER (ruler)); + + if (metric == NULL) + ruler->metric = (GtkCustomMetric *) & default_metric; + else + ruler->metric = metric; + + if (GTK_WIDGET_DRAWABLE (ruler)) + gtk_widget_queue_draw (GTK_WIDGET (ruler)); +} + +void +gtk_custom_ruler_set_range (GtkCustomRuler * ruler, gulong lower, gulong upper, gulong position, gulong max_size) +{ + g_return_if_fail (ruler != NULL); + g_return_if_fail (GTK_IS_CUSTOM_RULER (ruler)); + + ruler->lower = lower; + ruler->upper = upper; + ruler->position = position; + ruler->max_size = max_size; + + if (GTK_WIDGET_DRAWABLE (ruler)) + gtk_widget_queue_draw (GTK_WIDGET (ruler)); +} + +void +gtk_custom_ruler_draw_ticks (GtkCustomRuler * ruler) +{ + GtkCustomRulerClass *klass; + g_return_if_fail (ruler != NULL); + g_return_if_fail (GTK_IS_CUSTOM_RULER (ruler)); + + klass = GTK_CUSTOM_RULER_CLASS (GTK_OBJECT (ruler)->klass); + if (klass->draw_ticks) + klass->draw_ticks (ruler); +} + +void +gtk_custom_ruler_draw_pos (GtkCustomRuler * ruler) +{ + GtkCustomRulerClass *klass; + g_return_if_fail (ruler != NULL); + g_return_if_fail (GTK_IS_CUSTOM_RULER (ruler)); + + klass = GTK_CUSTOM_RULER_CLASS (GTK_OBJECT (ruler)->klass); + if (klass->draw_pos && ruler->show_position) + klass->draw_pos (ruler); +} + +static void +gtk_custom_ruler_realize (GtkWidget * widget) +{ + GtkCustomRuler *ruler; + GdkWindowAttr attributes; + gint attributes_mask; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_CUSTOM_RULER (widget)); + + ruler = GTK_CUSTOM_RULER (widget); + GTK_WIDGET_SET_FLAGS (ruler, GTK_REALIZED); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + attributes.event_mask = gtk_widget_get_events (widget); + attributes.event_mask |= (GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + + widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); + gdk_window_set_user_data (widget->window, ruler); + + widget->style = gtk_style_attach (widget->style, widget->window); + gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE); + + gtk_custom_ruler_make_pixmap (ruler); +} + +static void +gtk_custom_ruler_unrealize (GtkWidget * widget) +{ + GtkCustomRuler *ruler; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_CUSTOM_RULER (widget)); + + ruler = GTK_CUSTOM_RULER (widget); + + if (ruler->backing_store) + gdk_pixmap_unref (ruler->backing_store); + if (ruler->non_gr_exp_gc) + gdk_gc_destroy (ruler->non_gr_exp_gc); + + ruler->backing_store = NULL; + ruler->non_gr_exp_gc = NULL; + + if (GTK_WIDGET_CLASS (parent_class)->unrealize) + (*GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); +} + +static void +gtk_custom_ruler_size_allocate (GtkWidget * widget, GtkAllocation * allocation) +{ + GtkCustomRuler *ruler; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_CUSTOM_RULER (widget)); + + ruler = GTK_CUSTOM_RULER (widget); + widget->allocation = *allocation; + + if (GTK_WIDGET_REALIZED (widget)) { + gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height); + + gtk_custom_ruler_make_pixmap (ruler); + } +} + +static gint +gtk_custom_ruler_expose (GtkWidget * widget, GdkEventExpose * event) +{ + GtkCustomRuler *ruler; + + g_return_val_if_fail (widget != NULL, FALSE); + g_return_val_if_fail (GTK_IS_CUSTOM_RULER (widget), FALSE); + g_return_val_if_fail (event != NULL, FALSE); + + if (GTK_WIDGET_DRAWABLE (widget)) { + ruler = GTK_CUSTOM_RULER (widget); + + gtk_custom_ruler_draw_ticks (ruler); + + gdk_draw_pixmap (widget->window, + ruler->non_gr_exp_gc, + ruler->backing_store, 0, 0, 0, 0, widget->allocation.width, widget->allocation.height); + + gtk_custom_ruler_draw_pos (ruler); + } + + return FALSE; +} + +static void +gtk_custom_ruler_make_pixmap (GtkCustomRuler * ruler) +{ + GtkWidget *widget; + gint width; + gint height; + + widget = GTK_WIDGET (ruler); + + if (ruler->backing_store) { + gdk_window_get_size (ruler->backing_store, &width, &height); + if ((width == widget->allocation.width) && (height == widget->allocation.height)) + return; + + gdk_pixmap_unref (ruler->backing_store); + } + + ruler->backing_store = gdk_pixmap_new (widget->window, widget->allocation.width, widget->allocation.height, -1); + + ruler->xsrc = 0; + ruler->ysrc = 0; + + if (!ruler->non_gr_exp_gc) { + ruler->non_gr_exp_gc = gdk_gc_new (widget->window); + gdk_gc_set_exposures (ruler->non_gr_exp_gc, FALSE); + } +} + +void +gtk_custom_ruler_set_show_position (GtkCustomRuler * ruler, gboolean yn) +{ + ruler->show_position = yn; +} diff --git a/gtk2_ardour/gtk-custom-ruler.h b/gtk2_ardour/gtk-custom-ruler.h new file mode 100644 index 0000000000..da280abed5 --- /dev/null +++ b/gtk2_ardour/gtk-custom-ruler.h @@ -0,0 +1,111 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +/* modified by andreas meyer */ + +#ifndef __GTK_CUSTOM_RULER_H__ +#define __GTK_CUSTOM_RULER_H__ + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define GTK_TYPE_CUSTOM_RULER (gtk_custom_ruler_get_type ()) +#define GTK_CUSTOM_RULER(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_CUSTOM_RULER, GtkCustomRuler)) +#define GTK_CUSTOM_RULER_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_CUSTOM_RULER, GtkCustomRulerClass)) +#define GTK_IS_CUSTOM_RULER(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_CUSTOM_RULER)) +#define GTK_IS_CUSTOM_RULER_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_CUSTOM_RULER)) + +typedef struct _GtkCustomRuler GtkCustomRuler; +typedef struct _GtkCustomRulerClass GtkCustomRulerClass; +typedef struct _GtkCustomMetric GtkCustomMetric; +typedef struct _GtkCustomRulerMark GtkCustomRulerMark; + +struct _GtkCustomRuler { + GtkWidget widget; + + GdkPixmap *backing_store; + GdkGC *non_gr_exp_gc; + GtkCustomMetric *metric; + gint xsrc, ysrc; + gint slider_size; + gboolean show_position; + + /* The upper limit of the ruler (in points) */ + gulong lower; + /* The lower limit of the ruler */ + gulong upper; + /* The position of the mark on the ruler */ + gulong position; + /* The maximum size of the ruler */ + gulong max_size; +}; + +struct _GtkCustomRulerClass { + GtkWidgetClass parent_class; + + void (* draw_ticks) (GtkCustomRuler *ruler); + void (* draw_pos) (GtkCustomRuler *ruler); +}; + +typedef enum { + GtkCustomRulerMarkMajor, + GtkCustomRulerMarkMinor, + GtkCustomRulerMarkMicro +} GtkCustomRulerMarkStyle; + +struct _GtkCustomRulerMark { + gchar *label; + gulong position; + GtkCustomRulerMarkStyle style; +}; + +struct _GtkCustomMetric { + gfloat units_per_pixel; + gint (* get_marks) (GtkCustomRulerMark **marks, gulong lower, gulong upper, gint maxchars); +}; + +GtkType gtk_custom_ruler_get_type (void); +void gtk_custom_ruler_set_metric (GtkCustomRuler *ruler, GtkCustomMetric *metric); +void gtk_custom_ruler_set_range (GtkCustomRuler *ruler, + gulong lower, + gulong upper, + gulong position, + gulong max_size); +void gtk_custom_ruler_draw_ticks (GtkCustomRuler *ruler); +void gtk_custom_ruler_draw_pos (GtkCustomRuler *ruler); +void gtk_custom_ruler_set_show_position (GtkCustomRuler *rule, gboolean yn); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GTK_CUSTOM_RULER_H__ */ diff --git a/gtk2_ardour/gtkscrolledwindow.c b/gtk2_ardour/gtkscrolledwindow.c new file mode 100644 index 0000000000..329660c06e --- /dev/null +++ b/gtk2_ardour/gtkscrolledwindow.c @@ -0,0 +1,972 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#include +#include + + +/* scrolled window policy and size requisition handling: + * + * gtk size requisition works as follows: + * a widget upon size-request reports the width and height that it finds + * to be best suited to display its contents, including children. + * the width and/or height reported from a widget upon size requisition + * may be overidden by the user by specifying a width and/or height + * other than 0 through gtk_widget_set_usize(). + * + * a scrolled window needs (for imlementing all three policy types) to + * request its width and height based on two different rationales. + * 1) the user wants the scrolled window to just fit into the space + * that it gets allocated for a specifc dimension. + * 1.1) this does not apply if the user specified a concrete value + * value for that specific dimension by either specifying usize for the + * scrolled window or for its child. + * 2) the user wants the scrolled window to take as much space up as + * is desired by the child for a specifc dimension (i.e. POLICY_NEVER). + * + * also, kinda obvious: + * 3) a user would certainly not have choosen a scrolled window as a container + * for the child, if the resulting allocation takes up more space than the + * child would have allocated without the scrolled window. + * + * conclusions: + * A) from 1) follows: the scrolled window shouldn't request more space for a + * specifc dimension than is required at minimum. + * B) from 1.1) follows: the requisition may be overidden by usize of the scrolled + * window (done automatically) or by usize of the child (needs to be checked). + * C) from 2) follows: for POLICY_NEVER, the scrolled window simply reports the + * child's dimension. + * D) from 3) follows: the scrolled window child's minimum width and minimum height + * under A) at least correspond to the space taken up by its scrollbars. + */ + +#define SCROLLBAR_SPACING(w) (GTK_SCROLLED_WINDOW_CLASS (GTK_OBJECT (w)->klass)->scrollbar_spacing) + +#define DEFAULT_SCROLLBAR_SPACING 3 + +enum { + ARG_0, + ARG_HADJUSTMENT, + ARG_VADJUSTMENT, + ARG_HSCROLLBAR_POLICY, + ARG_VSCROLLBAR_POLICY, + ARG_WINDOW_PLACEMENT +}; + + +static void gtk_scrolled_window_class_init (GtkScrolledWindowClass *klass); +static void gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window); +static void gtk_scrolled_window_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void gtk_scrolled_window_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id); +static void gtk_scrolled_window_destroy (GtkObject *object); +static void gtk_scrolled_window_finalize (GtkObject *object); +static void gtk_scrolled_window_map (GtkWidget *widget); +static void gtk_scrolled_window_unmap (GtkWidget *widget); +static void gtk_scrolled_window_draw (GtkWidget *widget, + GdkRectangle *area); +static void gtk_scrolled_window_size_request (GtkWidget *widget, + GtkRequisition *requisition); +static void gtk_scrolled_window_size_allocate (GtkWidget *widget, + GtkAllocation *allocation); +static void gtk_scrolled_window_add (GtkContainer *container, + GtkWidget *widget); +static void gtk_scrolled_window_remove (GtkContainer *container, + GtkWidget *widget); +static void gtk_scrolled_window_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data); +static void gtk_scrolled_window_relative_allocation(GtkWidget *widget, + GtkAllocation *allocation); +static void gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment, + gpointer data); + + +static GtkContainerClass *parent_class = NULL; + + +GtkType +gtk_scrolled_window_get_type (void) +{ + static GtkType scrolled_window_type = 0; + + if (!scrolled_window_type) + { + static const GtkTypeInfo scrolled_window_info = + { + "GtkScrolledWindow", + sizeof (GtkScrolledWindow), + sizeof (GtkScrolledWindowClass), + (GtkClassInitFunc) gtk_scrolled_window_class_init, + (GtkObjectInitFunc) gtk_scrolled_window_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + scrolled_window_type = gtk_type_unique (GTK_TYPE_BIN, &scrolled_window_info); + } + + return scrolled_window_type; +} + +static void +gtk_scrolled_window_class_init (GtkScrolledWindowClass *class) +{ + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + object_class = (GtkObjectClass*) class; + widget_class = (GtkWidgetClass*) class; + container_class = (GtkContainerClass*) class; + parent_class = gtk_type_class (GTK_TYPE_BIN); + + gtk_object_add_arg_type ("GtkScrolledWindow::hadjustment", + GTK_TYPE_ADJUSTMENT, + GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT, + ARG_HADJUSTMENT); + gtk_object_add_arg_type ("GtkScrolledWindow::vadjustment", + GTK_TYPE_ADJUSTMENT, + GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT, + ARG_VADJUSTMENT); + gtk_object_add_arg_type ("GtkScrolledWindow::hscrollbar_policy", + GTK_TYPE_POLICY_TYPE, + GTK_ARG_READWRITE, + ARG_HSCROLLBAR_POLICY); + gtk_object_add_arg_type ("GtkScrolledWindow::vscrollbar_policy", + GTK_TYPE_POLICY_TYPE, + GTK_ARG_READWRITE, + ARG_VSCROLLBAR_POLICY); + gtk_object_add_arg_type ("GtkScrolledWindow::window_placement", + GTK_TYPE_CORNER_TYPE, + GTK_ARG_READWRITE, + ARG_WINDOW_PLACEMENT); + + object_class->set_arg = gtk_scrolled_window_set_arg; + object_class->get_arg = gtk_scrolled_window_get_arg; + object_class->destroy = gtk_scrolled_window_destroy; + object_class->finalize = gtk_scrolled_window_finalize; + + widget_class->map = gtk_scrolled_window_map; + widget_class->unmap = gtk_scrolled_window_unmap; + widget_class->draw = gtk_scrolled_window_draw; + widget_class->size_request = gtk_scrolled_window_size_request; + widget_class->size_allocate = gtk_scrolled_window_size_allocate; + + container_class->add = gtk_scrolled_window_add; + container_class->remove = gtk_scrolled_window_remove; + container_class->forall = gtk_scrolled_window_forall; + + class->scrollbar_spacing = DEFAULT_SCROLLBAR_SPACING; +} + +static void +gtk_scrolled_window_set_arg (GtkObject *object, + GtkArg *arg, + guint arg_id) +{ + GtkScrolledWindow *scrolled_window; + + scrolled_window = GTK_SCROLLED_WINDOW (object); + + switch (arg_id) + { + case ARG_HADJUSTMENT: + gtk_scrolled_window_set_hadjustment (scrolled_window, GTK_VALUE_POINTER (*arg)); + break; + case ARG_VADJUSTMENT: + gtk_scrolled_window_set_vadjustment (scrolled_window, GTK_VALUE_POINTER (*arg)); + break; + case ARG_HSCROLLBAR_POLICY: + gtk_scrolled_window_set_policy (scrolled_window, + GTK_VALUE_ENUM (*arg), + scrolled_window->vscrollbar_policy); + break; + case ARG_VSCROLLBAR_POLICY: + gtk_scrolled_window_set_policy (scrolled_window, + scrolled_window->hscrollbar_policy, + GTK_VALUE_ENUM (*arg)); + break; + case ARG_WINDOW_PLACEMENT: + gtk_scrolled_window_set_placement (scrolled_window, + GTK_VALUE_ENUM (*arg)); + break; + default: + break; + } +} + +static void +gtk_scrolled_window_get_arg (GtkObject *object, + GtkArg *arg, + guint arg_id) +{ + GtkScrolledWindow *scrolled_window; + + scrolled_window = GTK_SCROLLED_WINDOW (object); + + switch (arg_id) + { + case ARG_HADJUSTMENT: + GTK_VALUE_POINTER (*arg) = gtk_scrolled_window_get_hadjustment (scrolled_window); + break; + case ARG_VADJUSTMENT: + GTK_VALUE_POINTER (*arg) = gtk_scrolled_window_get_vadjustment (scrolled_window); + break; + case ARG_HSCROLLBAR_POLICY: + GTK_VALUE_ENUM (*arg) = scrolled_window->hscrollbar_policy; + break; + case ARG_VSCROLLBAR_POLICY: + GTK_VALUE_ENUM (*arg) = scrolled_window->vscrollbar_policy; + break; + case ARG_WINDOW_PLACEMENT: + GTK_VALUE_ENUM (*arg) = scrolled_window->window_placement; + break; + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + +static void +gtk_scrolled_window_init (GtkScrolledWindow *scrolled_window) +{ + GTK_WIDGET_SET_FLAGS (scrolled_window, GTK_NO_WINDOW); + + gtk_container_set_resize_mode (GTK_CONTAINER (scrolled_window), GTK_RESIZE_QUEUE); + + scrolled_window->hscrollbar = NULL; + scrolled_window->vscrollbar = NULL; + scrolled_window->hscrollbar_policy = GTK_POLICY_ALWAYS; + scrolled_window->vscrollbar_policy = GTK_POLICY_ALWAYS; + scrolled_window->hscrollbar_visible = FALSE; + scrolled_window->vscrollbar_visible = FALSE; + scrolled_window->window_placement = GTK_CORNER_TOP_LEFT; +} + +GtkWidget* +gtk_scrolled_window_new (GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment) +{ + GtkWidget *scrolled_window; + + if (hadjustment) + g_return_val_if_fail (GTK_IS_ADJUSTMENT (hadjustment), NULL); + + if (vadjustment) + g_return_val_if_fail (GTK_IS_ADJUSTMENT (vadjustment), NULL); + + scrolled_window = gtk_widget_new (GTK_TYPE_SCROLLED_WINDOW, + "hadjustment", hadjustment, + "vadjustment", vadjustment, + NULL); + + return scrolled_window; +} + +void +gtk_scrolled_window_set_hadjustment (GtkScrolledWindow *scrolled_window, + GtkAdjustment *hadjustment) +{ + GtkBin *bin; + + g_return_if_fail (scrolled_window != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); + if (hadjustment) + g_return_if_fail (GTK_IS_ADJUSTMENT (hadjustment)); + else + hadjustment = (GtkAdjustment*) gtk_object_new (GTK_TYPE_ADJUSTMENT, NULL); + + bin = GTK_BIN (scrolled_window); + + if (!scrolled_window->hscrollbar) + { + gtk_widget_push_composite_child (); + scrolled_window->hscrollbar = gtk_hscrollbar_new (hadjustment); + gtk_widget_set_composite_name (scrolled_window->hscrollbar, "hscrollbar"); + gtk_widget_pop_composite_child (); + + gtk_widget_set_parent (scrolled_window->hscrollbar, GTK_WIDGET (scrolled_window)); + gtk_widget_ref (scrolled_window->hscrollbar); + gtk_widget_show (scrolled_window->hscrollbar); + } + else + { + GtkAdjustment *old_adjustment; + + old_adjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)); + if (old_adjustment == hadjustment) + return; + + gtk_signal_disconnect_by_func (GTK_OBJECT (old_adjustment), + GTK_SIGNAL_FUNC (gtk_scrolled_window_adjustment_changed), + scrolled_window); + gtk_range_set_adjustment (GTK_RANGE (scrolled_window->hscrollbar), + hadjustment); + } + hadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)); + gtk_signal_connect (GTK_OBJECT (hadjustment), + "changed", + GTK_SIGNAL_FUNC (gtk_scrolled_window_adjustment_changed), + scrolled_window); + gtk_scrolled_window_adjustment_changed (hadjustment, scrolled_window); + + if (bin->child) + gtk_widget_set_scroll_adjustments (bin->child, + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)), + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar))); +} + +void +gtk_scrolled_window_set_vadjustment (GtkScrolledWindow *scrolled_window, + GtkAdjustment *vadjustment) +{ + GtkBin *bin; + + g_return_if_fail (scrolled_window != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); + if (vadjustment) + g_return_if_fail (GTK_IS_ADJUSTMENT (vadjustment)); + else + vadjustment = (GtkAdjustment*) gtk_object_new (GTK_TYPE_ADJUSTMENT, NULL); + + bin = GTK_BIN (scrolled_window); + + if (!scrolled_window->vscrollbar) + { + gtk_widget_push_composite_child (); + scrolled_window->vscrollbar = gtk_vscrollbar_new (vadjustment); + gtk_widget_set_composite_name (scrolled_window->vscrollbar, "vscrollbar"); + gtk_widget_pop_composite_child (); + + gtk_widget_set_parent (scrolled_window->vscrollbar, GTK_WIDGET (scrolled_window)); + gtk_widget_ref (scrolled_window->vscrollbar); + gtk_widget_show (scrolled_window->vscrollbar); + } + else + { + GtkAdjustment *old_adjustment; + + old_adjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)); + if (old_adjustment == vadjustment) + return; + + gtk_signal_disconnect_by_func (GTK_OBJECT (old_adjustment), + GTK_SIGNAL_FUNC (gtk_scrolled_window_adjustment_changed), + scrolled_window); + gtk_range_set_adjustment (GTK_RANGE (scrolled_window->vscrollbar), + vadjustment); + } + vadjustment = gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)); + gtk_signal_connect (GTK_OBJECT (vadjustment), + "changed", + GTK_SIGNAL_FUNC (gtk_scrolled_window_adjustment_changed), + scrolled_window); + gtk_scrolled_window_adjustment_changed (vadjustment, scrolled_window); + + if (bin->child) + gtk_widget_set_scroll_adjustments (bin->child, + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)), + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar))); +} + +GtkAdjustment* +gtk_scrolled_window_get_hadjustment (GtkScrolledWindow *scrolled_window) +{ + g_return_val_if_fail (scrolled_window != NULL, NULL); + g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), NULL); + + return (scrolled_window->hscrollbar ? + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)) : + NULL); +} + +GtkAdjustment* +gtk_scrolled_window_get_vadjustment (GtkScrolledWindow *scrolled_window) +{ + g_return_val_if_fail (scrolled_window != NULL, NULL); + g_return_val_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window), NULL); + + return (scrolled_window->vscrollbar ? + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)) : + NULL); +} + +void +gtk_scrolled_window_set_policy (GtkScrolledWindow *scrolled_window, + GtkPolicyType hscrollbar_policy, + GtkPolicyType vscrollbar_policy) +{ + g_return_if_fail (scrolled_window != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); + + if ((scrolled_window->hscrollbar_policy != hscrollbar_policy) || + (scrolled_window->vscrollbar_policy != vscrollbar_policy)) + { + scrolled_window->hscrollbar_policy = hscrollbar_policy; + scrolled_window->vscrollbar_policy = vscrollbar_policy; + + gtk_widget_queue_resize (GTK_WIDGET (scrolled_window)); + } +} + +void +gtk_scrolled_window_set_placement (GtkScrolledWindow *scrolled_window, + GtkCornerType window_placement) +{ + g_return_if_fail (scrolled_window != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); + + if (scrolled_window->window_placement != window_placement) + { + scrolled_window->window_placement = window_placement; + + gtk_widget_queue_resize (GTK_WIDGET (scrolled_window)); + } +} + +static void +gtk_scrolled_window_destroy (GtkObject *object) +{ + GtkScrolledWindow *scrolled_window; + + g_return_if_fail (object != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (object)); + + scrolled_window = GTK_SCROLLED_WINDOW (object); + + gtk_widget_unparent (scrolled_window->hscrollbar); + gtk_widget_unparent (scrolled_window->vscrollbar); + gtk_widget_destroy (scrolled_window->hscrollbar); + gtk_widget_destroy (scrolled_window->vscrollbar); + + GTK_OBJECT_CLASS (parent_class)->destroy (object); +} + +static void +gtk_scrolled_window_finalize (GtkObject *object) +{ + GtkScrolledWindow *scrolled_window; + + scrolled_window = GTK_SCROLLED_WINDOW (object); + + gtk_widget_unref (scrolled_window->hscrollbar); + gtk_widget_unref (scrolled_window->vscrollbar); + + GTK_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gtk_scrolled_window_map (GtkWidget *widget) +{ + GtkScrolledWindow *scrolled_window; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget)); + + scrolled_window = GTK_SCROLLED_WINDOW (widget); + + /* chain parent class handler to map self and child */ + GTK_WIDGET_CLASS (parent_class)->map (widget); + + if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar) && + !GTK_WIDGET_MAPPED (scrolled_window->hscrollbar)) + gtk_widget_map (scrolled_window->hscrollbar); + + if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar) && + !GTK_WIDGET_MAPPED (scrolled_window->vscrollbar)) + gtk_widget_map (scrolled_window->vscrollbar); +} + +static void +gtk_scrolled_window_unmap (GtkWidget *widget) +{ + GtkScrolledWindow *scrolled_window; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget)); + + scrolled_window = GTK_SCROLLED_WINDOW (widget); + + /* chain parent class handler to unmap self and child */ + GTK_WIDGET_CLASS (parent_class)->unmap (widget); + + if (GTK_WIDGET_MAPPED (scrolled_window->hscrollbar)) + gtk_widget_unmap (scrolled_window->hscrollbar); + + if (GTK_WIDGET_MAPPED (scrolled_window->vscrollbar)) + gtk_widget_unmap (scrolled_window->vscrollbar); +} + +static void +gtk_scrolled_window_draw (GtkWidget *widget, + GdkRectangle *area) +{ + GtkScrolledWindow *scrolled_window; + GtkBin *bin; + GdkRectangle child_area; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget)); + g_return_if_fail (area != NULL); + + scrolled_window = GTK_SCROLLED_WINDOW (widget); + bin = GTK_BIN (widget); + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child) && + gtk_widget_intersect (bin->child, area, &child_area)) + gtk_widget_draw (bin->child, &child_area); + + if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar) && + gtk_widget_intersect (scrolled_window->hscrollbar, area, &child_area)) + gtk_widget_draw (scrolled_window->hscrollbar, &child_area); + + if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar) && + gtk_widget_intersect (scrolled_window->vscrollbar, area, &child_area)) + gtk_widget_draw (scrolled_window->vscrollbar, &child_area); +} + +static void +gtk_scrolled_window_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (container)); + g_return_if_fail (callback != NULL); + + GTK_CONTAINER_CLASS (parent_class)->forall (container, + include_internals, + callback, + callback_data); + if (include_internals) + { + GtkScrolledWindow *scrolled_window; + + scrolled_window = GTK_SCROLLED_WINDOW (container); + + if (scrolled_window->vscrollbar) + callback (scrolled_window->vscrollbar, callback_data); + if (scrolled_window->hscrollbar) + callback (scrolled_window->hscrollbar, callback_data); + } +} + +static void +gtk_scrolled_window_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + GtkScrolledWindow *scrolled_window; + GtkBin *bin; + gint extra_width; + gint extra_height; + GtkRequisition hscrollbar_requisition; + GtkRequisition vscrollbar_requisition; + GtkRequisition child_requisition; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget)); + g_return_if_fail (requisition != NULL); + + scrolled_window = GTK_SCROLLED_WINDOW (widget); + bin = GTK_BIN (scrolled_window); + + extra_width = 0; + extra_height = 0; + requisition->width = 0; + requisition->height = 0; + + gtk_widget_size_request (scrolled_window->hscrollbar, + &hscrollbar_requisition); + gtk_widget_size_request (scrolled_window->vscrollbar, + &vscrollbar_requisition); + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + { + static guint quark_aux_info = 0; + + if (!quark_aux_info) + quark_aux_info = g_quark_from_static_string ("gtk-aux-info"); + + gtk_widget_size_request (bin->child, &child_requisition); + + if (scrolled_window->hscrollbar_policy == GTK_POLICY_NEVER) + requisition->width += child_requisition.width; + else + { + GtkWidgetAuxInfo *aux_info; + + aux_info = gtk_object_get_data_by_id (GTK_OBJECT (bin->child), quark_aux_info); + if (aux_info && aux_info->width > 0) + { + requisition->width += aux_info->width; + extra_width = -1; + } + else + requisition->width += vscrollbar_requisition.width; + } + +// if (scrolled_window->vscrollbar_policy == GTK_POLICY_NEVER) +// requisition->height += child_requisition.height; +// else + { + GtkWidgetAuxInfo *aux_info; + + aux_info = gtk_object_get_data_by_id (GTK_OBJECT (bin->child), quark_aux_info); + if (aux_info && aux_info->height > 0) + { + requisition->height += aux_info->height; + extra_height = -1; + } + else + requisition->height += hscrollbar_requisition.height; + } + } + + if (scrolled_window->hscrollbar_policy == GTK_POLICY_AUTOMATIC || + scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS) + { + requisition->width = MAX (requisition->width, hscrollbar_requisition.width); + if (!extra_height || scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS) + extra_height = SCROLLBAR_SPACING (scrolled_window) + hscrollbar_requisition.height; + } + + if (scrolled_window->vscrollbar_policy == GTK_POLICY_AUTOMATIC || + scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS) + { + requisition->height = MAX (requisition->height, vscrollbar_requisition.height); + if (!extra_height || scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS) + extra_width = SCROLLBAR_SPACING (scrolled_window) + vscrollbar_requisition.width; + } + + requisition->width += GTK_CONTAINER (widget)->border_width * 2 + MAX (0, extra_width); + requisition->height += GTK_CONTAINER (widget)->border_width * 2 + MAX (0, extra_height); +} + +static void +gtk_scrolled_window_relative_allocation (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkScrolledWindow *scrolled_window; + + g_return_if_fail (widget != NULL); + g_return_if_fail (allocation != NULL); + + scrolled_window = GTK_SCROLLED_WINDOW (widget); + + allocation->x = GTK_CONTAINER (widget)->border_width; + allocation->y = GTK_CONTAINER (widget)->border_width; + allocation->width = MAX (1, (gint)widget->allocation.width - allocation->x * 2); + allocation->height = MAX (1, (gint)widget->allocation.height - allocation->y * 2); + + if (scrolled_window->vscrollbar_visible) + { + GtkRequisition vscrollbar_requisition; + gtk_widget_get_child_requisition (scrolled_window->vscrollbar, + &vscrollbar_requisition); + + if (scrolled_window->window_placement == GTK_CORNER_TOP_RIGHT || + scrolled_window->window_placement == GTK_CORNER_BOTTOM_RIGHT) + allocation->x += (vscrollbar_requisition.width + + SCROLLBAR_SPACING (scrolled_window)); + + allocation->width = MAX (1, (gint)allocation->width - + ((gint)vscrollbar_requisition.width + + (gint)SCROLLBAR_SPACING (scrolled_window))); + } + if (scrolled_window->hscrollbar_visible) + { + GtkRequisition hscrollbar_requisition; + gtk_widget_get_child_requisition (scrolled_window->hscrollbar, + &hscrollbar_requisition); + + if (scrolled_window->window_placement == GTK_CORNER_BOTTOM_LEFT || + scrolled_window->window_placement == GTK_CORNER_BOTTOM_RIGHT) + allocation->y += (hscrollbar_requisition.height + + SCROLLBAR_SPACING (scrolled_window)); + + allocation->height = MAX (1, (gint)allocation->height - + ((gint)hscrollbar_requisition.height + + (gint)SCROLLBAR_SPACING (scrolled_window))); + } +} + +static void +gtk_scrolled_window_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkScrolledWindow *scrolled_window; + GtkBin *bin; + GtkAllocation relative_allocation; + GtkAllocation child_allocation; + + g_return_if_fail (widget != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (widget)); + g_return_if_fail (allocation != NULL); + + scrolled_window = GTK_SCROLLED_WINDOW (widget); + bin = GTK_BIN (scrolled_window); + + widget->allocation = *allocation; + + if (scrolled_window->hscrollbar_policy == GTK_POLICY_ALWAYS) + scrolled_window->hscrollbar_visible = TRUE; + else if (scrolled_window->hscrollbar_policy == GTK_POLICY_NEVER) + scrolled_window->hscrollbar_visible = FALSE; + if (scrolled_window->vscrollbar_policy == GTK_POLICY_ALWAYS) + scrolled_window->vscrollbar_visible = TRUE; + else if (scrolled_window->vscrollbar_policy == GTK_POLICY_NEVER) + scrolled_window->vscrollbar_visible = FALSE; + + if (bin->child && GTK_WIDGET_VISIBLE (bin->child)) + { + gboolean previous_hvis; + gboolean previous_vvis; + guint count = 0; + + do + { + gtk_scrolled_window_relative_allocation (widget, &relative_allocation); + + child_allocation.x = relative_allocation.x + allocation->x; + child_allocation.y = relative_allocation.y + allocation->y; + child_allocation.width = relative_allocation.width; + child_allocation.height = relative_allocation.height; + + previous_hvis = scrolled_window->hscrollbar_visible; + previous_vvis = scrolled_window->vscrollbar_visible; + + gtk_widget_size_allocate (bin->child, &child_allocation); + + /* If, after the first iteration, the hscrollbar and the + * vscrollbar flip visiblity, then we need both. + */ + if (count && + previous_hvis != scrolled_window->hscrollbar_visible && + previous_vvis != scrolled_window->vscrollbar_visible) + { + scrolled_window->hscrollbar_visible = TRUE; + scrolled_window->vscrollbar_visible = TRUE; + + /* a new resize is already queued at this point, + * so we will immediatedly get reinvoked + */ + return; + } + + count++; + } + while (previous_hvis != scrolled_window->hscrollbar_visible || + previous_vvis != scrolled_window->vscrollbar_visible); + } + else + gtk_scrolled_window_relative_allocation (widget, &relative_allocation); + + if (scrolled_window->hscrollbar_visible) + { + GtkRequisition hscrollbar_requisition; + gtk_widget_get_child_requisition (scrolled_window->hscrollbar, + &hscrollbar_requisition); + + if (!GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar)) + gtk_widget_show (scrolled_window->hscrollbar); + + child_allocation.x = relative_allocation.x; + if (scrolled_window->window_placement == GTK_CORNER_TOP_LEFT || + scrolled_window->window_placement == GTK_CORNER_TOP_RIGHT) + child_allocation.y = (relative_allocation.y + + relative_allocation.height + + SCROLLBAR_SPACING (scrolled_window)); + else + child_allocation.y = GTK_CONTAINER (scrolled_window)->border_width; + + child_allocation.width = relative_allocation.width; + child_allocation.height = hscrollbar_requisition.height; + child_allocation.x += allocation->x; + child_allocation.y += allocation->y; + + gtk_widget_size_allocate (scrolled_window->hscrollbar, &child_allocation); + } + else if (GTK_WIDGET_VISIBLE (scrolled_window->hscrollbar)) + gtk_widget_hide (scrolled_window->hscrollbar); + + if (scrolled_window->vscrollbar_visible) + { + GtkRequisition vscrollbar_requisition; + if (!GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar)) + gtk_widget_show (scrolled_window->vscrollbar); + + gtk_widget_get_child_requisition (scrolled_window->vscrollbar, + &vscrollbar_requisition); + + if (scrolled_window->window_placement == GTK_CORNER_TOP_LEFT || + scrolled_window->window_placement == GTK_CORNER_BOTTOM_LEFT) + child_allocation.x = (relative_allocation.x + + relative_allocation.width + + SCROLLBAR_SPACING (scrolled_window)); + else + child_allocation.x = GTK_CONTAINER (scrolled_window)->border_width; + + child_allocation.y = relative_allocation.y; + child_allocation.width = vscrollbar_requisition.width; + child_allocation.height = relative_allocation.height; + child_allocation.x += allocation->x; + child_allocation.y += allocation->y; + + gtk_widget_size_allocate (scrolled_window->vscrollbar, &child_allocation); + } + else if (GTK_WIDGET_VISIBLE (scrolled_window->vscrollbar)) + gtk_widget_hide (scrolled_window->vscrollbar); +} + + +static void +gtk_scrolled_window_adjustment_changed (GtkAdjustment *adjustment, + gpointer data) +{ + GtkScrolledWindow *scrolled_win; + + g_return_if_fail (adjustment != NULL); + g_return_if_fail (data != NULL); + + scrolled_win = GTK_SCROLLED_WINDOW (data); + + if (adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_win->hscrollbar))) + { + if (scrolled_win->hscrollbar_policy == GTK_POLICY_AUTOMATIC) + { + gboolean visible; + + visible = scrolled_win->hscrollbar_visible; + scrolled_win->hscrollbar_visible = (adjustment->upper - adjustment->lower > + adjustment->page_size); + if (scrolled_win->hscrollbar_visible != visible) + gtk_widget_queue_resize (GTK_WIDGET (scrolled_win)); + } + } + else if (adjustment == gtk_range_get_adjustment (GTK_RANGE (scrolled_win->vscrollbar))) + { + if (scrolled_win->vscrollbar_policy == GTK_POLICY_AUTOMATIC) + { + gboolean visible; + + visible = scrolled_win->vscrollbar_visible; + scrolled_win->vscrollbar_visible = (adjustment->upper - adjustment->lower > + adjustment->page_size); + if (scrolled_win->vscrollbar_visible != visible) + gtk_widget_queue_resize (GTK_WIDGET (scrolled_win)); + } + } +} + +static void +gtk_scrolled_window_add (GtkContainer *container, + GtkWidget *child) +{ + GtkScrolledWindow *scrolled_window; + GtkBin *bin; + + bin = GTK_BIN (container); + g_return_if_fail (bin->child == NULL); + + scrolled_window = GTK_SCROLLED_WINDOW (container); + + bin->child = child; + gtk_widget_set_parent (child, GTK_WIDGET (bin)); + + /* this is a temporary message */ + if (!gtk_widget_set_scroll_adjustments (child, + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->hscrollbar)), + gtk_range_get_adjustment (GTK_RANGE (scrolled_window->vscrollbar)))) + g_warning ("gtk_scrolled_window_add(): cannot add non scrollable widget " + "use gtk_scrolled_window_add_with_viewport() instead"); + + if (GTK_WIDGET_REALIZED (child->parent)) + gtk_widget_realize (child); + + if (GTK_WIDGET_VISIBLE (child->parent) && GTK_WIDGET_VISIBLE (child)) + { + if (GTK_WIDGET_MAPPED (child->parent)) + gtk_widget_map (child); + + gtk_widget_queue_resize (child); + } +} + +static void +gtk_scrolled_window_remove (GtkContainer *container, + GtkWidget *child) +{ + g_return_if_fail (container != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (container)); + g_return_if_fail (child != NULL); + g_return_if_fail (GTK_BIN (container)->child == child); + + gtk_widget_set_scroll_adjustments (child, NULL, NULL); + + /* chain parent class handler to remove child */ + GTK_CONTAINER_CLASS (parent_class)->remove (container, child); +} + +void +gtk_scrolled_window_add_with_viewport (GtkScrolledWindow *scrolled_window, + GtkWidget *child) +{ + GtkBin *bin; + GtkWidget *viewport; + + g_return_if_fail (scrolled_window != NULL); + g_return_if_fail (GTK_IS_SCROLLED_WINDOW (scrolled_window)); + g_return_if_fail (child != NULL); + g_return_if_fail (GTK_IS_WIDGET (child)); + g_return_if_fail (child->parent == NULL); + + bin = GTK_BIN (scrolled_window); + + if (bin->child != NULL) + { + g_return_if_fail (GTK_IS_VIEWPORT (bin->child)); + g_return_if_fail (GTK_BIN (bin->child)->child == NULL); + + viewport = bin->child; + } + else + { + viewport = + gtk_viewport_new (gtk_scrolled_window_get_hadjustment (scrolled_window), + gtk_scrolled_window_get_vadjustment (scrolled_window)); + gtk_container_add (GTK_CONTAINER (scrolled_window), viewport); + } + + gtk_widget_show (viewport); + gtk_container_add (GTK_CONTAINER (viewport), child); +} diff --git a/gtk2_ardour/gui_thread.h b/gtk2_ardour/gui_thread.h new file mode 100644 index 0000000000..7b09007d80 --- /dev/null +++ b/gtk2_ardour/gui_thread.h @@ -0,0 +1,10 @@ +#ifndef __ardour_gtk_gui_thread_h__ +#define __ardour_gtk_gui_thread_h__ + +#define ENSURE_GUI_THREAD(slot) \ + if (!Gtkmmext::UI::instance()->caller_is_gui_thread()) {\ + Gtkmmext::UI::instance()->call_slot ((slot));\ + return;\ + } + +#endif /* __ardour_gtk_gui_thread_h__ */ diff --git a/gtk2_ardour/i18n.h b/gtk2_ardour/i18n.h new file mode 100644 index 0000000000..3ace250419 --- /dev/null +++ b/gtk2_ardour/i18n.h @@ -0,0 +1,16 @@ +#ifndef __i18n_h__ +#define __i18n_h__ + +#include +#include "gettext.h" + +#include +#include + +std::vector internationalize (const char **); + +#define _(Text) dgettext (PACKAGE,Text) +#define N_(Text) gettext_noop (Text) +#define X_(Text) Text + +#endif // __i18n_h__ diff --git a/gtk2_ardour/imageframe_socket_handler.cc b/gtk2_ardour/imageframe_socket_handler.cc new file mode 100644 index 0000000000..938984c82f --- /dev/null +++ b/gtk2_ardour/imageframe_socket_handler.cc @@ -0,0 +1,2353 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "imageframe_socket_handler.h" +#include "imageframe_time_axis.h" +#include "imageframe_time_axis_view.h" +#include "imageframe_time_axis_group.h" +#include "imageframe_view.h" +#include "marker_time_axis.h" +#include "marker_time_axis_view.h" +#include "ardour_ui.h" +#include "public_editor.h" +#include "extra_bind.h" +#include "gui_thread.h" + +#include "i18n.h" + +#include + +#include +#include + +using namespace std; +using namespace ardourvis ; +using namespace SigC; + +ImageFrameSocketHandler* ImageFrameSocketHandler::_instance = 0 ; + +/** + * Constructs a new ImageFrameSocketHandler to handle communication between Ardour and the Image Compositor + * + * @param ed the PublicEditor + */ +ImageFrameSocketHandler::ImageFrameSocketHandler(PublicEditor& ed) : thePublicEditor(ed), theArdourToCompositorSocket(-1) +{ + +} + +/** + * Descructor + * this will shutdown the socket if open + */ +ImageFrameSocketHandler::~ImageFrameSocketHandler() +{ + close_connection() ; +} + + +/** + * Returns the instance of the ImageFrameSocketHandler + * the instance should first be created with createInstance + * + * @return the instance of the ImageFrameSocketHandler + */ +ImageFrameSocketHandler* +ImageFrameSocketHandler::get_instance() +{ + return(_instance) ; +} + +/** + * Create an new instance of the ImageFrameSocketHandler, if one does not already exist + * + * @param ed the Ardour PublicEditor + */ +ImageFrameSocketHandler* +ImageFrameSocketHandler::create_instance(PublicEditor& ed) +{ + if(_instance) + { + return(_instance) ; + } + else + { + _instance = new ImageFrameSocketHandler(ed) ; + return(_instance) ; + } +} + +/** + * call back to handle doing the processing work + * This method is added to the gdk main loop and called when there is data + * upon the socket. + * + */ +void +ImageFrameSocketHandler::image_socket_callback(void *arg, int32_t fd, GdkInputCondition cond) +{ + char buf[ardourvis::MAX_MSG_SIZE + 1] ; + memset(buf, 0, (ardourvis::MAX_MSG_SIZE + 1)) ; + buf[ardourvis::MAX_MSG_SIZE] = '\0' ; + + int retcode = ::recv(fd, buf, MAX_MSG_SIZE, 0) ; + if (retcode == 0) + { + //end-of-file, other end closed or shutdown? + ARDOUR_UI::instance()->popup_error(_("Image Compositor Socket has been shutdown/closed")); + + // assume socket has been shutdown, tell, someone interested, + // and remove the socket from the event loop + ImageFrameSocketHandler* ifsh = ImageFrameSocketHandler::get_instance() ; + gdk_input_remove(ifsh->theGdkInputTag) ; + ifsh->close_connection() ; + ifsh->CompositorSocketShutdown() ; /* EMIT_SIGNAL */ + } + if(retcode > 0) + { + //std::cout << "Received Msg [" << buf << "]\n" ; + ImageFrameSocketHandler* ifsh = ImageFrameSocketHandler::get_instance() ; + + std::string mType = ifsh->get_message_part(0,2,buf) ; + + if(mType == ardourvis::INSERT_ITEM) + { + ifsh->handle_insert_message(buf) ; + } + else if (mType == ardourvis::REMOVE_ITEM) + { + ifsh->handle_remove_message(buf) ; + } + else if (mType == ardourvis::RENAME_ITEM) + { + ifsh->handle_rename_message(buf) ; + } + else if (mType == ardourvis::ITEM_UPDATE) + { + ifsh->handle_item_update_message(buf) ; + } + else if (mType == ardourvis::REQUEST_DATA) + { + ifsh->handle_request_data(buf) ; + } + else if (mType == ardourvis::ITEM_SELECTED) + { + ifsh->handle_item_selected(buf) ; + } + else if(mType == ardourvis::SESSION_ACTION) + { + ifsh->handle_session_action(buf) ; + } + else + { + std::string errMsg = "Unknown Message type : " ; + errMsg.append(mType) ; + ifsh->send_return_failure(errMsg) ; + } + } +} + +/** + * Attempt to connect to the image compositor on the specified host and port + * + * @param hostIp the ip address of the image compositor host + * @param port the oprt number to attemp the connection on + * @return true if the connection was a succees + * false otherwise + */ +bool +ImageFrameSocketHandler::connect(std::string hostIp, int32_t port) +{ + if (is_connected()) + { + //already connected... + return(true) ; + } + + theArdourToCompositorSocket = socket(AF_INET, SOCK_STREAM, 0) ; + if(theArdourToCompositorSocket == -1) + { + return(false) ; + } + + int on = 1 ; + setsockopt(theArdourToCompositorSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) ; + + sockaddr_in m_addr ; + m_addr.sin_family = AF_INET ; + m_addr.sin_port = htons(port) ; + m_addr.sin_addr.s_addr = inet_addr(hostIp.c_str()) ; + + int status = ::connect(theArdourToCompositorSocket, (sockaddr *) &m_addr, sizeof(m_addr)) ; + + if(status == -1) + { + theArdourToCompositorSocket = -1 ; + return(false) ; + } + + return(true) ; +} + +/** + * Closes the connection to th Image Compositor + * + */ + void + ImageFrameSocketHandler::close_connection() + { + if(is_connected()) + { + ::close(theArdourToCompositorSocket) ; + theArdourToCompositorSocket = -1 ; + } + } + +/** + * Returns true if this ImagFrameSocketHandler is currently connected to rthe image compositor + * + * @return true if connected to the image compositor + */ +bool +ImageFrameSocketHandler::is_connected() +{ + return(theArdourToCompositorSocket == -1 ? false : true) ; +} + +/** + * Sets the tag used to describe this input within gtk + * this is returned when gdk_input_add is called and is required to remove the input + * + * @param tag the gdk input tag of this input + */ +void +ImageFrameSocketHandler::set_gdk_input_tag(int tag) +{ + theGdkInputTag = tag ; +} + +/** + * Returns the gdk input tag of this input + * + * @return the gdk input tag of this input + * @see setGdkInputTag + */ +int +ImageFrameSocketHandler::get_gdk_input_tag() +{ + return(theGdkInputTag) ; +} + +/** + * Returns the socket file descriptor + * + * @return the Sockt file descriptor + */ +int +ImageFrameSocketHandler::get_socket_descriptor() +{ + return(theArdourToCompositorSocket) ; +} + + + + +//---------------------------------------------------------------------------------------// +// Handle Sending messages to the Image Compositor + +//---------------------------- +// ImageFrameTimeAxis Messages + +/** + * Sends a message stating that the named image frame time axis has been removed + * + * @param track_id the unique id of the removed image frame time axis + * @param src the identity of the object that initiated the change + */ +void +ImageFrameSocketHandler::send_imageframe_time_axis_removed(std::string track_id, void* src) +{ + if(this == src || src == 0) + { + // ie the change originated from us, then dont send any message back + return ; + } + + // create a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::IMAGEFRAME_TIME_AXIS ; + + // add the id length, and the id + msgBuffer << std::setw(3) << track_id.length() ; + msgBuffer << track_id ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + +/** + * Sends a message indicating that an ImageFrameTimeAxis has been renamed + * + * @param new_id the new name, or Id, of the track + * @param old_id the old name, or Id, of the track + * @param src the identity of the object that initiated the change + * @param time_axis the time axis that has changed + */ +void +ImageFrameSocketHandler::send_imageframe_time_axis_renamed(std::string new_id, std::string old_id, void* src, ImageFrameTimeAxis* time_axis) +{ + // ENSURE_GUI_THREAD(SigC::bind (slot (*this, &ImageFrameSocketHandler::send_imageframe_time_axis_renamed), new_id, old_id, src, time_axis)); + + if(this == src || src == 0) + { + // ie the change originated from us, then dont send any message back + return ; + } + + // create a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::RENAME_ITEM << ardourvis::IMAGEFRAME_TIME_AXIS ; + + // add the old id and length + msgBuffer << std::setw(3) << old_id.length() ; + msgBuffer << old_id ; + + // add the new id and length + msgBuffer << std::setw(3) << new_id.length() ; + msgBuffer << new_id ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + +//------------------------ +// MarkerTimeAxis Messages + +/** + * Sends a message stating that the named marker time axis has been removed + * + * @param track_id the unique id of the removed image frame time axis + * @param src the identity of the object that initiated the change + */ +void +ImageFrameSocketHandler::send_marker_time_axis_removed(std::string track_id, void* src) +{ + if(this == src || src == 0) + { + // ie the change originated from us, then dont send any message back + return ; + } + + // create a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::MARKER_TIME_AXIS ; + + // add the id length, and the id + msgBuffer << std::setw(3) << track_id.length() ; + msgBuffer << track_id ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + +/** + * Sends a message indicating that an MarkerTimeAxis has been renamed + * + * @param new_id the new name, or Id, of the track + * @param old_id the old name, or Id, of the track + * @param src the identity of the object that initiated the change + * @param time_axis the time axis that has changed + */ +void +ImageFrameSocketHandler::send_marker_time_axis_renamed(std::string new_id, std::string old_id, void* src, MarkerTimeAxis* time_axis) +{ + // ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameSocketHandler::send_marker_time_axis_renamed), new_id, old_id, src, time_axis)); + + if(this == src || src == 0) + { + // ie the change originated from us, then dont send any message back + return ; + } + + // ctreate a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::RENAME_ITEM << ardourvis::MARKER_TIME_AXIS ; + + // add the old id and length + msgBuffer << std::setw(3) << old_id.length() ; + msgBuffer << old_id ; + + // add the new id and length + msgBuffer << std::setw(3) << new_id.length() ; + msgBuffer << new_id ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + +//--------------------------------- +// ImageFrameTimeAxisGroup Messages + +/** + * Sends a message stating that the group has been removed + * + * @param group_id the unique id of the removed image frame time axis + * @param src the identity of the object that initiated the change + * @param group the group that has changed + */ +void +ImageFrameSocketHandler::send_imageframe_time_axis_group_removed(std::string group_id, void* src, ImageFrameTimeAxisGroup* group) +{ + if(this == src || src == 0) + { + // ie the change originated from us, then dont send any message back + return ; + } + + // create a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::IMAGEFRAME_GROUP ; + + // add the id length, and the id of the parent image time axis + std::string track_id = group->get_view().trackview().name() ; + msgBuffer << std::setw(3) << track_id.length() ; + msgBuffer << track_id ; + + // add the group id and length + msgBuffer << std::setw(3) << group_id.length() ; + msgBuffer << group_id ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + +/** + * Send a message indicating that an ImageFrameTimeAxisGroup has been renamed + * + * @param new_id the new name, or Id, of the group + * @param old_id the old name, or Id, of the group + * @param src the identity of the object that initiated the change + * @param group the group that has changed + */ +void +ImageFrameSocketHandler::send_imageframe_time_axis_group_renamed(std::string new_id, std::string old_id, void* src, ImageFrameTimeAxisGroup* group) +{ + // ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameSocketHandler::send_imageframe_time_axis_group_renamed), new_id, old_id, src, group)); + + if(this == src || src == 0) + { + // ie the change originated from us, then dont send any message back + return ; + } + + // ctreate a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::RENAME_ITEM << ardourvis::IMAGEFRAME_GROUP ; + + // add the track this group is upon + std::string track_id = group->get_view().trackview().name() ; + msgBuffer << std::setw(3) << track_id.length() << track_id ; + + // add the old id and length + msgBuffer << std::setw(3) << old_id.length() ; + msgBuffer << old_id ; + + // add the new id and length + msgBuffer << std::setw(3) << new_id.length() ; + msgBuffer << new_id ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + + +//--------------------------------- +// ImageFrameView Messages + +/** + * Send an Image Frame View Item position changed message + * + * @param pos the new position value + * @param src the identity of the object that initiated the change + * @param item the time axis item whos position has changed + */ +void +ImageFrameSocketHandler::send_imageframe_view_position_change(jack_nframes_t pos, void* src, ImageFrameView* item) +{ + // ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameSocketHandler::send_imageframe_view_position_change), pos, src, item)); + + if(this == src || src == 0) + { + return ; + } + + // create a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::IMAGEFRAME_ITEM << ardourvis::POSITION_CHANGE ; + + // add the item description + this->compose_imageframe_item_desc(item, msgBuffer) ; + + msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << pos ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + +/** + * Send a Image Frame View item duration changed message + * + * @param dur the the new duration value + * @param src the identity of the object that initiated the change + * @param item the item which has had a duration change + */ +void +ImageFrameSocketHandler::send_imageframe_view_duration_change(jack_nframes_t dur, void* src, ImageFrameView* item) +{ + // ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameSocketHandler::send_imageframe_view_duration_change), dur, src, item)); + + if(this == src || src == 0) + { + return ; + } + + // create a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::IMAGEFRAME_ITEM << ardourvis::DURATION_CHANGE ; + + this->compose_imageframe_item_desc(item, msgBuffer) ; + + msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << dur ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + +/** + * Send a message indicating that an ImageFrameView has been renamed + * + * @param item the ImageFrameView which has been renamed + * @param src the identity of the object that initiated the change + * @param item the renamed item + */ +void +ImageFrameSocketHandler::send_imageframe_view_renamed(std::string new_id, std::string old_id, void* src, ImageFrameView* item) +{ + if(this == src || src == 0) + { + // ie the change originated from us, then dont send any message back + return ; + } + + // ctreate a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::RENAME_ITEM << ardourvis::IMAGEFRAME_ITEM ; + + this->compose_imageframe_item_desc(item, msgBuffer) ; + + // add the old id and length + msgBuffer << std::setw(3) << old_id.length() ; + msgBuffer << old_id ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + +/** + * Send a message indicating that an ImageFrameView item has been removed message + * + * @param item_id the id of the item that was removed + * @param item the removed item + */ +void +ImageFrameSocketHandler::send_imageframe_view_removed(std::string item_id, void* src, ImageFrameView* item) +{ + if(this == src || src == 0) + { + // ie the change originated from us, then dont send any message back + return ; + } + + // create a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::IMAGEFRAME_ITEM ; + + // add the id length, and the id + ImageFrameTimeAxisGroup* parentGroup = item->get_time_axis_group() ; + std::string group_id = parentGroup->get_group_name() ; + std::string track_id = parentGroup->get_view().trackview().name() ; + msgBuffer << std::setw(3) << track_id.length() << track_id ; + msgBuffer << std::setw(3) << group_id.length() << group_id ; + msgBuffer << std::setw(3) << item_id.length() << item_id ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + + + + +//--------------------------------- +// MarkerView Messages + +/** + * Send a Marker View Item position changed message + * + * @param pos the new position value + * @param src the identity of the object that initiated the change + * @param item the time axis item whos position has changed + */ +void +ImageFrameSocketHandler::send_marker_view_position_change(jack_nframes_t pos, void* src, MarkerView* item) +{ + if(this == src || src == 0) + { + return ; + } + + // create a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::MARKER_ITEM << ardourvis::POSITION_CHANGE ; + + // add the item description + this->compose_marker_item_desc(item, msgBuffer) ; + + msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << pos ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + +/** + * Send a Marker View item duration changed message + * + * @param dur the new duration value + * @param src the identity of the object that initiated the change + * @param item the time axis item whos position has changed + */ +void +ImageFrameSocketHandler::send_marker_view_duration_change(jack_nframes_t dur, void* src, MarkerView* item) +{ + if(this == src || src == 0) + { + return ; + } + + // create a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::ITEM_UPDATE << ardourvis::MARKER_ITEM << ardourvis::DURATION_CHANGE ; + + this->compose_marker_item_desc(item, msgBuffer) ; + + msgBuffer << std::setw(ardourvis::TIME_VALUE_CHARS) << dur ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + + +/** + * Send a message indicating that a MarkerView has been renamed + * + * @param new_id the new_id of the object + * @param old_id the old_id of the object + * @param src the identity of the object that initiated the change + * @param item the MarkerView which has been renamed + */ +void +ImageFrameSocketHandler::send_marker_view_renamed(std::string new_id, std::string old_id, void* src, MarkerView* item) +{ + if(this == src || src == 0) + { + // ie the change originated from us, then dont send any message back + return ; + } + + // ctreate a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::RENAME_ITEM << ardourvis::MARKER_ITEM ; + + this->compose_marker_item_desc(item, msgBuffer) ; + + // add the old id and length + msgBuffer << std::setw(3) << old_id.length() ; + msgBuffer << old_id ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + +/** + * Send a message indicating that a MarkerView item has been removed message + * + * @param item_id the id of the item that was removed + * @param src the identity of the object that initiated the change + * @param item the MarkerView which has been removed + */ +void +ImageFrameSocketHandler::send_marker_view_removed(std::string item_id, void* src, MarkerView* item) +{ + if(this == src || src == 0) + { + // ie the change originated from us, then dont send any message back + return ; + } + + // create a message buffer + std::ostringstream msgBuffer ; + msgBuffer << std::setfill('0') ; + + // add the msg type + msgBuffer << ardourvis::REMOVE_ITEM << ardourvis::MARKER_ITEM ; + + // add the id length, and the id + std::string track_id = item->get_time_axis_view().name() ; + msgBuffer << std::setw(3) << track_id.length() << track_id ; + msgBuffer << std::setw(3) << item_id.length() << item_id ; + + send_message(msgBuffer.str()) ; + + // XXX should do something with the return + std::string retmsg ; + read_message(retmsg) ; +} + + + + + + + + + + + +//---------------------------------------------------------------------------------------// +//---------------------------------------------------------------------------------------// +//---------------------------------------------------------------------------------------// +// Message breakdown ie avoid a big if...then...else + + +/** + * Handle insert item requests + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_insert_message(const char* msg) +{ + // handle the insert item message + // determine the object type to insert based upon characters 2-3 + + std::string oType = get_message_part(2,2,msg) ; + + if(oType == ardourvis::IMAGEFRAME_TIME_AXIS) + { + this->handle_insert_imageframe_time_axis(msg) ; + } + else if (oType == ardourvis::MARKER_TIME_AXIS) + { + this->handle_insert_marker_time_axis(msg) ; + } + else if (oType == ardourvis::IMAGEFRAME_GROUP) + { + this->handle_insert_imageframe_group(msg) ; + } + else if (oType == ardourvis::IMAGEFRAME_ITEM) + { + this->handle_insert_imageframe_view(msg) ; + } + else if (oType == ardourvis::MARKER_ITEM) + { + this->handle_insert_marker_view(msg) ; + } + else + { + std::string errMsg = "Unknown Object type during insert: " ; + errMsg.append(oType) ; + send_return_failure(errMsg) ; + } +} + +/** + * Handle remove item requests + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_remove_message(const char* msg) +{ + // handle the removal of an item message + // determine the object type to remove based upon characters 2-3 + + std::string oType = get_message_part(2,2,msg) ; + + if(oType == ardourvis::IMAGEFRAME_TIME_AXIS) + { + this->handle_remove_imageframe_time_axis(msg) ; + } + else if (oType == ardourvis::MARKER_TIME_AXIS) + { + this->handle_remove_marker_time_axis(msg) ; + } + else if (oType == ardourvis::IMAGEFRAME_ITEM) + { + this->handle_remove_imageframe_view(msg) ; + } + else if (oType == ardourvis::MARKER_ITEM) + { + this->handle_remove_marker_view(msg) ; + } + else + { + std::string errMsg = "Unknown Object type during Remove: " ; + errMsg.append(oType) ; + send_return_failure(errMsg) ; + } +} + +/** + * Handle rename item requests + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_rename_message(const char* msg) +{ + // handle the renaming of an item message + // determine the object type to rename based upon characters 2-3 + + std::string oType = get_message_part(2,2,msg) ; + + if(oType == ardourvis::IMAGEFRAME_TIME_AXIS) + { + this->handle_rename_imageframe_time_axis(msg) ; + } + else if (oType == ardourvis::MARKER_TIME_AXIS) + { + this->handle_rename_marker_time_axis(msg) ; + } + else if (oType == ardourvis::IMAGEFRAME_ITEM) + { + this->handle_rename_imageframe_view(msg) ; + } + else if (oType == ardourvis::MARKER_ITEM) + { + this->handle_rename_marker_view(msg) ; + } + else + { + std::string errMsg = "Unknown Object type during Rename: " ; + errMsg.append(oType) ; + send_return_failure(errMsg) ; + } +} + +/** + * Handle a request for session information + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_request_data(const char* msg) +{ + // determine the request type + std::string reqType = get_message_part(2,2,msg) ; + + if(reqType == ardourvis::SESSION_NAME) + { + handle_session_name_request(msg) ; + } +} + +/** + * Handle the update of a particular item + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_item_update_message(const char* msg) +{ + // determin the object that requires updating, characters 2-3 + std::string oType = get_message_part(2,2,msg) ; + + // What needs updating? chars 4-5 + std::string attr = get_message_part(4,2,msg) ; + + if(oType == ardourvis::IMAGEFRAME_ITEM) + { + if(attr == ardourvis::POSITION_CHANGE) + { + handle_imageframe_view_position_update(msg) ; + } + else if(attr == ardourvis::DURATION_CHANGE) + { + handle_imageframe_view_duration_update(msg) ; + } + else if(attr == ardourvis::POSITION_LOCK_CHANGE) + { + handle_imageframe_position_lock_update(msg) ; + } + else if(attr == ardourvis::MAX_DURATION_CHANGE) + { + handle_imageframe_view_max_duration_update(msg) ; + } + else if(attr == ardourvis::MAX_DURATION_ENABLE_CHANGE) + { + handle_imageframe_view_max_duration_enable_update(msg) ; + } + else if(attr == ardourvis::MIN_DURATION_CHANGE) + { + handle_imageframe_view_min_duration_update(msg) ; + } + else if(attr == ardourvis::MIN_DURATION_ENABLE_CHANGE) + { + handle_imageframe_view_min_duration_enable_update(msg) ; + } + else + { + std::string errMsg = "Unknown Attribute during Item Update: " ; + errMsg.append(oType) ; + send_return_failure(errMsg) ; + } + } + else if(oType == ardourvis::MARKER_ITEM) + { + if(attr == ardourvis::POSITION_CHANGE) + { + handle_marker_view_position_update(msg) ; + } + else if(attr == ardourvis::DURATION_CHANGE) + { + handle_marker_view_duration_update(msg) ; + } + else + { + std::string errMsg = "Unknown Attribute during Item Update: " ; + errMsg.append(oType) ; + send_return_failure(errMsg) ; + } + } + else + { + std::string errMsg = "Unknown Object type during Item Update: " ; + errMsg.append(oType) ; + send_return_failure(errMsg) ; + } +} + +/** + * Handle the selection of an Item + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_item_selected(const char* msg) +{ + // determine the object that requires updating, characters 2-3 + std::string oType = get_message_part(2,2,msg) ; + + if(oType == std::string(ardourvis::IMAGEFRAME_ITEM)) + { + int position = 4 ; // message type chars + + std::string track_id ; + std::string scene_id ; + std::string item_id ; + int track_id_size ; + int scene_id_size ; + int item_id_size ; + + this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, scene_id, scene_id_size, item_id, item_id_size) ; + + // get the named time axis + ImageFrameTimeAxis* ifta = dynamic_cast(thePublicEditor.get_named_time_axis(track_id)) ; + + if(!ifta) + { + send_return_failure(std::string("No parent Image Track found : ").append(track_id)) ; + } + else + { + // get the parent scene + ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_id) ; + if(!iftag) + { + send_return_failure(std::string("No parent Scene found : ").append(scene_id)) ; + } + else + { + ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ; + if(!ifv) + { + send_return_failure(std::string("No Image Frame Item found : ").append(item_id)) ; + } + else + { + ifv->set_selected(true, this) ; + ifta->get_view()->set_selected_imageframe_view(iftag, ifv) ; + + thePublicEditor.scroll_timeaxis_to_imageframe_item(ifv) ; + send_return_success() ; + } + } + } + } +} + +/** + * Handle s session action message + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_session_action(const char* msg) +{ + std::string actionType = get_message_part(2,2,msg) ; + + if(actionType == ardourvis::OPEN_SESSION) + { + this->handle_open_session(msg) ; + } +} + + + + + + + + + +//---------------------------------------------------------------------------------------// +// handlers for specific insert procedures + +/** + * Handle the insertion of a new ImaegFrameTimeAxis + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_insert_imageframe_time_axis(const char* msg) +{ + int position = 4 ; // message type chars + + // get the ImageFrameTrack name size + int track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ; + position += ardourvis::TEXT_SIZE_CHARS ; + + // get the image frame track name + std::string track_name = get_message_part(position, track_name_size, msg) ; + position += track_name_size ; + + // check we dont already have an time axis with that name + TimeAxisView* tav = thePublicEditor.get_named_time_axis(track_name) ; + if(tav) + { + std::string errmsg("Track already exists: ") ; + errmsg.append(track_name) ; + send_return_failure(errmsg) ; + } + else + { + thePublicEditor.add_imageframe_time_axis(track_name, this) ; + TimeAxisView* new_tav = thePublicEditor.get_named_time_axis(track_name) ; + + if(new_tav) + { + ImageFrameTimeAxis* ifta = (ImageFrameTimeAxis*)new_tav ; + ifta->VisualTimeAxisRemoved.connect(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_removed)) ; + ifta->NameChanged.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_renamed), ifta)) ; + + send_return_success() ; + } + else + { + std::string msg("Addition Failed: ") ; + msg.append(track_name) ; + send_return_failure(msg) ; + } + } +} + + +/** + * Handle the insertion of a new MarkerTimeAxis + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_insert_marker_time_axis(const char* msg) +{ + int position = 4 ; // message type chars + + // get the ImageFrameTrack name size + int track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ; + position += ardourvis::TEXT_SIZE_CHARS ; + + // get the image frame track name + std::string track_name = get_message_part(position, track_name_size, msg) ; + position += track_name_size ; + + // get the size of the name of the associated track + int assoc_track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ; + position += ardourvis::TEXT_SIZE_CHARS ; + + // get the name of the track we associate the marker track with + std::string assoc_track_name = get_message_part(position, assoc_track_name_size, msg) ; + position += assoc_track_name_size ; + + // check that we dont already have a time axis with that name + TimeAxisView* checkTav = thePublicEditor.get_named_time_axis(track_name) ; + if(checkTav) + { + std::string errmsg("Track already exists: ") ; + errmsg.append(track_name) ; + send_return_failure(errmsg) ; + } + else + { + // check the associated time axis exists + TimeAxisView* assoc_tav = thePublicEditor.get_named_time_axis(assoc_track_name) ; + if(assoc_tav) + { + thePublicEditor.add_imageframe_marker_time_axis(track_name, assoc_tav, this) ; + TimeAxisView* new_tav = thePublicEditor.get_named_time_axis(track_name) ; + + bool added = false ; + + if(new_tav) + { + MarkerTimeAxis* mta = dynamic_cast(new_tav) ; + if(mta) + { + added = true ; + mta->VisualTimeAxisRemoved.connect(SigC::slot(*this, &ImageFrameSocketHandler::send_marker_time_axis_removed)) ; + mta->NameChanged.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_marker_time_axis_renamed), mta)) ; + } + } + + if(added) + { + std::string msg("Addition Failed: ") ; + msg.append(track_name) ; + send_return_failure(msg) ; + } + } + else + { + std::string errmsg("No associated Track Found: ") ; + errmsg.append(track_name) ; + send_return_failure(errmsg) ; + } + } +} + +/** + * Handle the insertion of a time axis group (a scene) + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_insert_imageframe_group(const char* msg) +{ + int position = 4 ; // message type chars + + // get the ImageFrameTrack name size + int track_name_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ; + position += ardourvis::TEXT_SIZE_CHARS ; + + // get the image frame track name + std::string track_name = get_message_part(position, track_name_size, msg) ; + position += track_name_size ; + + // get the scene id size + int scene_id_size = atoi(get_message_part(position, ardourvis::TEXT_SIZE_CHARS, msg).c_str()) ; + position += ardourvis::TEXT_SIZE_CHARS ; + + // get the scene id + std::string scene_id = get_message_part(position, scene_id_size, msg) ; + position += scene_id_size ; + + + // get the named ImageFrameTrack + ImageFrameTimeAxis* ifta = dynamic_cast(thePublicEditor.get_named_time_axis(track_name)) ; + + // check we got a valid ImageFrameTimeAxis + if(!ifta) + { + send_return_failure(std::string("No Image Frame Time Axis Found: ").append(track_name)) ; + return ; + } + + ImageFrameTimeAxisGroup* iftag = ifta->get_view()->add_imageframe_group(scene_id, this) ; + if(!iftag) + { + send_return_failure(std::string("Image Frame Group insert failed")) ; + } + else + { + iftag->NameChanged.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_group_renamed), iftag)) ; + iftag->GroupRemoved.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_time_axis_group_removed), iftag)) ; + send_return_success() ; + } +} + + +/** + * Handle the insertion of a new ImageFrameItem + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_insert_imageframe_view(const char* msg) +{ + int position = 4 ; // message type chars + + // get the ImageFrameTrack name size + int track_name_size = atoi(get_message_part(position,3,msg).c_str()) ; + position += 3 ; + + // get the ImageFrameTrack Name + std::string imageframe_track_name = get_message_part(position,track_name_size,msg) ; + position += track_name_size ; + + // get the scene name size + int scene_size = atoi(get_message_part(position,3,msg).c_str()) ; + position += 3 ; + + // get the scene Name + std::string scene_name = get_message_part(position,scene_size,msg) ; + position += scene_size ; + + // get the image frame_id size + int image_id_size = atoi(get_message_part(position,3,msg).c_str()) ; + position += 3 ; + + // get the image frame_id + std::string image_id = get_message_part(position,image_id_size,msg) ; + position += image_id_size ; + + // get the start frame value + jack_nframes_t start = strtoul((get_message_part(position,10,msg).c_str()),0,10) ; + position += 10 ; + + // get the duration value + jack_nframes_t duration = strtoul((get_message_part(position,10,msg).c_str()),0,10) ; + position += 10 ; + + //get the named time axis view we about to add an image to + TimeAxisView* tav = thePublicEditor.get_named_time_axis(imageframe_track_name) ; + ImageFrameTimeAxis* ifta = 0 ; + + if(tav) + { + ifta = dynamic_cast(tav) ; + } + + if(!ifta) + { + std::string errmsg("No Parent Image Track Found: ") ; + errmsg.append(imageframe_track_name) ; + send_return_failure(errmsg) ; + + // dont really like all these returns mid-way + // but this is goinf to get awfully if..then nested if not + return ; + } + + // check the parent group exists + ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_name) ; + if(!iftag) + { + std::string errmsg("No Image Frame Group Found: ") ; + errmsg.append(scene_name) ; + send_return_failure(errmsg) ; + return ; + } + + // ok, so we have the parent group and track, now we need dome image data + + + // + // request the image data from the image compositor + // + + // ctreate a message buffer + std::ostringstream reqBuffer ; + reqBuffer << std::setfill('0') ; + + // add the msg type + reqBuffer << REQUEST_DATA << IMAGE_RGB_DATA ; + + // add the image track and size + reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << track_name_size ; + reqBuffer << imageframe_track_name ; + + // add the scene id and size + reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << scene_size ; + reqBuffer << scene_name ; + + // add the image id and size + reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << image_id_size ; + reqBuffer << image_id ; + + // add the preferred image height + reqBuffer << std::setw(ardourvis::TEXT_SIZE_CHARS) << ifta->get_image_display_height() ; + + // send the request message + send_message(reqBuffer.str()) ; + + + // read the reply, the inital image data message + // this gives us the image dimensions and the expected size of the image data + // msg type(4) + image width(3) + height(3) + num channels(3) + size of the image data (32) + std::string init_image_data_msg ; + read_message(init_image_data_msg) ; + int init_msg_pos = 4 ; + + int imgWidth = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_SIZE_CHARS).c_str()) ; + init_msg_pos += ardourvis::IMAGE_SIZE_CHARS ; + int imgHeight = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_SIZE_CHARS).c_str()) ; + init_msg_pos += ardourvis::IMAGE_SIZE_CHARS ; + int imgChannels = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_SIZE_CHARS).c_str()) ; + init_msg_pos += ardourvis::IMAGE_SIZE_CHARS ; + int imgSize = atoi(init_image_data_msg.substr(init_msg_pos, ardourvis::IMAGE_DATA_MESSAGE_SIZE_CHARS).c_str()) ; + + // send a success msg + // we need to do this to keep things moving + send_return_success() ; + + // create our image rgb buffer, this holds the image data we receive + unsigned char* rgb_img_buf = new unsigned char[imgSize] ; + + int retcode = ::recv(theArdourToCompositorSocket, rgb_img_buf, imgSize, MSG_WAITALL) ; + + if(retcode != imgSize) + { + delete [] rgb_img_buf ; + send_return_failure("Could not create new Image Frame View : image data sizes did not match") ; + } + else + { + ImageFrameView* ifv = iftag->add_imageframe_item(image_id, start, duration, rgb_img_buf, (uint32_t)imgWidth, (uint32_t)imgHeight, (uint32_t)imgChannels, this) ; + if(ifv) + { + ifv->PositionChanged.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_view_position_change), ifv)) ; + ifv->DurationChanged.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_view_duration_change), ifv)) ; + ifv->ItemRemoved.connect(SigC::bind(SigC::slot(*this, &ImageFrameSocketHandler::send_imageframe_view_removed), ifv)) ; + + send_return_success() ; + } + else + { + //addition failed. assume duplicate item_id + send_return_failure("Could not create new Image Frame View") ; + } + } +} + + + +/** + * Handle the insertion of a new MarkerItem + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_insert_marker_view(const char* msg) +{} + + +//---------------------------------------------------------------------------------------// +// handlers for specific removal procedures + + +/** + * Handle the removal of an ImageTimeAxis + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_remove_imageframe_time_axis(const char* msg) +{} + +/** + * Handle the removal of an MarkerTimeAxis + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_remove_marker_time_axis(const char* msg) +{} + +/** + * Handle the removal of an ImageFrameTimeAxisGroup + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_remove_imageframe_time_axis_group(const char* msg) +{} + +/** + * Handle the removal of an ImageFrameItem + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_remove_imageframe_view(const char* msg) +{} + +/** + * Handle the removal of an MarkerItem + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_remove_marker_view(const char* msg) +{} + + + + + +//---------------------------------------------------------------------------------------// +// handlers for the specific rename procedures + +/** + * Handle the renaming of an ImageTimeAxis + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_rename_imageframe_time_axis(const char* msg) +{ + // msg [MVIT][oldSize][oldId][newSize][newId] + + int position = 4 ; // message type chars + + // get the old Id size + int old_id_size = atoi(get_message_part(position,3,msg).c_str()) ; + position += 3 ; + + // get the old id + std::string old_id = get_message_part(position,old_id_size,msg) ; + position += old_id_size ; + + //get the new Id size + int new_id_size = atoi(get_message_part(position,3,msg).c_str()) ; + position += 3 ; + + // get the new Id + std::string new_id = get_message_part(position,new_id_size,msg) ; + position += new_id_size ; + + // get the Named time axis + TimeAxisView* tav = thePublicEditor.get_named_time_axis(old_id) ; + if(dynamic_cast(tav)) + { + ImageFrameTimeAxis* ifta = dynamic_cast(tav) ; + ifta->set_time_axis_name(new_id, this) ; + send_return_success() ; + } + else + { + std::string msg = "No Image Track Found: " ; + msg.append(old_id) ; + send_return_failure(msg) ; + } +} + +/** + * Handle the renaming of an MarkerTimeAxis + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_rename_marker_time_axis(const char* msg) +{} + +/** + * Handle the renaming of an ImageFrameItem + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_rename_imageframe_time_axis_group(const char* msg) +{} + +/** + * Handle the renaming of an ImageFrameItem + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_rename_imageframe_view(const char* msg) +{} + +/** + * Handle the renaming of an Marker + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_rename_marker_view(const char* msg) +{} + + + + +//---------------------------------------------------------------------------------------// +// handlers for data request + +/** + * Handle a request for the sessnio naem fo the current session + * We return a failure state if no session is open + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_session_name_request(const char* msg) +{ + ARDOUR::Session* currentSession = thePublicEditor.current_session() ; + + if(currentSession == 0) + { + // no current session, return failure + std::string msg("No Current Session") ; + send_return_failure(msg) ; + } + else + { + std::string sessionName = currentSession->name() ; + std::string sessionPath = currentSession->path() ; + + if(sessionPath[sessionPath.length() -1] != '/') + { + sessionPath.append("/") ; + } + + sessionPath.append(sessionName) ; + + std::ostringstream msgBuf ; + msgBuf << ardourvis::RETURN_DATA << ardourvis::SESSION_NAME ; + msgBuf << std::setfill('0') ; + msgBuf << std::setw(ardourvis::TEXT_SIZE_CHARS) << sessionPath.length() ; + msgBuf << sessionPath ; + send_message(msgBuf.str()) ; + } +} + + + + + +//---------------------------------------------------------------------------------------// +// handlers for specific item update changes + +/** + * Handle ImageFrameView positional changes + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_imageframe_view_position_update(const char* msg) +{ + int position = 6 ; // message type chars + + std::string track_id ; + std::string scene_id ; + std::string item_id ; + int track_id_size ; + int scene_id_size ; + int item_id_size ; + + this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, scene_id, scene_id_size, item_id, item_id_size) ; + + jack_nframes_t start_frame = strtoul(get_message_part(position, ardourvis::TIME_VALUE_CHARS, msg).c_str(), 0, 10) ; + position += ardourvis::TIME_VALUE_CHARS ; + + // get the named time axis + ImageFrameTimeAxis* ifta = dynamic_cast(thePublicEditor.get_named_time_axis(track_id)) ; + + if(!ifta) + { + send_return_failure(std::string("No parent Image Track found: ").append(track_id)) ; + return ; + } + + // get the parent scene + ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_id) ; + if(!iftag) + { + send_return_failure(std::string("No parent Scene found: ").append(scene_id)) ; + return ; + } + + ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ; + + if(!ifv) + { + send_return_failure(std::string("No Image Frame Item found: ").append(item_id)) ; + return ; + } + + + ifv->set_position(start_frame, this) ; + send_return_success() ; +} + +/** + * Handle ImageFrameView Duration changes + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_imageframe_view_duration_update(const char* msg) +{ + int position = 6 ; // message type chars + + std::string track_id ; + std::string scene_id ; + std::string item_id ; + int track_id_size ; + int scene_id_size ; + int item_id_size ; + + this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, scene_id, scene_id_size, item_id, item_id_size) ; + + jack_nframes_t duration = strtoul(get_message_part(position,ardourvis::TIME_VALUE_CHARS,msg).c_str(),0,10) ; + position += ardourvis::TIME_VALUE_CHARS ; + + // get the named time axis + ImageFrameTimeAxis* ifta = dynamic_cast(thePublicEditor.get_named_time_axis(track_id)) ; + + if(!ifta) + { + send_return_failure(std::string("No parent Image Track found : ").append(track_id)) ; + return ; + } + + // get the parent scene + ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(scene_id) ; + if(!iftag) + { + send_return_failure(std::string("No parent Scene found : ").append(scene_id)) ; + return ; + } + + ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ; + + if(!ifv) + { + send_return_failure(std::string("No Image Frame Item found : ").append(item_id)) ; + return ; + } + + ifv->set_duration(duration, this) ; + send_return_success() ; +} + +/** + * Handle ImageFrameView Position Lock Constraint changes + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_imageframe_position_lock_update(const char* msg) +{ + int position = 6 ; // message type chars + + std::string track_id ; + std::string group_id ; + std::string item_id ; + int track_id_size ; + int group_id_size ; + int item_id_size ; + + this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ; + + std::string pos_lock = get_message_part(position,1,msg) ; + bool pos_lock_active = false ; + + if(pos_lock == "0") + { + pos_lock_active = false ; + } + else if(pos_lock == "1") + { + pos_lock_active = true ; + } + else + { + send_return_failure(std::string("Unknown Value used during Position Loack: ").append(pos_lock)) ; + return ; + } + + position += 1 ; + + int errcode ; + std::string errmsg ; + ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ; + if(ifv) + { + ifv->set_position_locked(pos_lock_active, this) ; + send_return_success() ; + } + else + { + send_return_failure(errmsg) ; + } +} + +/** + * Handle ImageFrameView Maximum Duration changes + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_imageframe_view_max_duration_update(const char* msg) +{ + int position = 6 ; // message type chars + + std::string track_id ; + std::string group_id ; + std::string item_id ; + int track_id_size ; + int group_id_size ; + int item_id_size ; + + this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ; + + jack_nframes_t max_duration = strtoul(get_message_part(position,ardourvis::TIME_VALUE_CHARS,msg).c_str(),0,10) ; + position += ardourvis::TIME_VALUE_CHARS ; + + int errcode ; + std::string errmsg ; + ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ; + if(ifv) + { + ifv->set_max_duration(max_duration, this) ; + send_return_success() ; + } + else + { + send_return_failure(errmsg) ; + } +} + +/** + * Handle image frame max duration enable constraint changes + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_imageframe_view_max_duration_enable_update(const char* msg) +{ + int position = 6 ; // message type chars + + std::string track_id ; + std::string group_id ; + std::string item_id ; + int track_id_size ; + int group_id_size ; + int item_id_size ; + + this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ; + + std::string active = get_message_part(position,1,msg) ; + bool max_duration_active = false ; + + if(active == "0") + { + max_duration_active = false ; + } + else if(active == "1") + { + max_duration_active = true ; + } + else + { + send_return_failure(std::string("Unknown Value used during enable max duration: ").append(active)) ; + return ; + } + + position += 1 ; + + int errcode ; + std::string errmsg ; + ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ; + if(ifv) + { + ifv->set_max_duration_active(max_duration_active, this) ; + send_return_success() ; + } + else + { + send_return_failure(errmsg) ; + } +} + +/** + * Handle ImageFrameView Minimum Duration changes + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_imageframe_view_min_duration_update(const char* msg) +{ + int position = 6 ; // message type chars + + std::string track_id ; + std::string group_id ; + std::string item_id ; + int track_id_size ; + int group_id_size ; + int item_id_size ; + + this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ; + + jack_nframes_t min_duration = strtoul(get_message_part(position,ardourvis::TIME_VALUE_CHARS,msg).c_str(),0,10) ; + position += ardourvis::TIME_VALUE_CHARS ; + + int errcode ; + std::string errmsg ; + ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ; + if(ifv) + { + ifv->set_min_duration(min_duration, this) ; + send_return_success() ; + } + else + { + send_return_failure(errmsg) ; + } +} + +/** + * Handle image frame min duration enable constraint changes + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_imageframe_view_min_duration_enable_update(const char* msg) +{ + int position = 6 ; // message type chars + + std::string track_id ; + std::string group_id ; + std::string item_id ; + int track_id_size ; + int group_id_size ; + int item_id_size ; + + this->decompose_imageframe_item_desc(msg, position, track_id, track_id_size, group_id, group_id_size, item_id, item_id_size) ; + + std::string active = get_message_part(position,1,msg) ; + bool min_duration_active = false ; + + if(active == "0") + { + min_duration_active = false ; + } + else if(active == "1") + { + min_duration_active = true ; + } + else + { + send_return_failure(std::string("Unknown Value used during enable max duration: ").append(active)) ; + return ; + } + + position += 1 ; + + int errcode ; + std::string errmsg ; + ImageFrameView* ifv = get_imageframe_view_from_desc(track_id, group_id, item_id, errcode, errmsg) ; + if(ifv) + { + ifv->set_min_duration_active(min_duration_active, this) ; + send_return_success() ; + } + else + { + send_return_failure(errmsg) ; + } +} + +/** + * Handle MarkerView position changes + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_marker_view_position_update(const char* msg) +{} + +/** + * Handle MarkerView duration changes + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_marker_view_duration_update(const char* msg) +{} + +/** + * Handle MarkerView Position Lock Constraint changes + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_marker_view_position_lock_update(const char* msg) +{ +} + +/** + * Handle MarkerView maximum duration changes + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_marker_view_max_duration_update(const char* msg) +{} + +/** + * Handle MarkerView minimum duration changes + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_marker_view_min_duration_update(const char* msg) +{} + + + + + +//---------------------------------------------------------------------------------------// +// handlers for Session Actions + +/** + * Handle the opening of a named audio session + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_open_session(const char* msg) +{ + // msg [SAOS][sessionSize][sessionPath] + + int position = 4 ; // message type chars + + // get the session name size + int session_name_size = atoi(get_message_part(position,3,msg).c_str()) ; + position += 3 ; + + // get the session name + std::string session_name = get_message_part(position,session_name_size,msg) ; + position += session_name_size ; + + + // open the session + std::string path, name ; + bool isnew; + + if (ARDOUR::Session::find_session(session_name, path, name, isnew) == 0) { + if (ARDOUR_UI::instance()->load_session (path, name) == 0) { + send_return_success() ; + } else { + std::string retMsg = "Failed to load Session" ; + send_return_failure(retMsg) ; + } + } else { + std::string retMsg = "Failed to find Session" ; + send_return_failure(retMsg) ; + } +} + + +/** + * Handle the closing of a named audio session + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_closed_session(const char* msg) +{} + +//---------------------------------------------------------------------------------------// +// handlers for the shutdown of the Image Compositor + +/** + * Handle the shutdown message from the image compositor + * + * @param msg the received message + */ +void +ImageFrameSocketHandler::handle_shutdown(const char* msg) +{ + CompositorSocketShutdown() ; /* EMIT_SIGNAL */ +} + + + + + + + + + + +//---------------------------------------------------------------------------------------// +// convenince methods to break up messages + +/** + * Returns part of the received message as a std::string + * + * @param start the start character + * @param num_chars the number of characters to read + * @param the message to break apart + * @return the sub string of the message + */ +std::string +ImageFrameSocketHandler::get_message_part(int start, int32_t num_chars, const char* msg) +{ + char buf[num_chars + 1] ; + strncpy(buf,msg+start,num_chars) ; + buf[num_chars] = '\0' ; + std::string s(buf) ; + + return(s) ; +} + + + +/** + * break up am image item description message + * we break the mesage up into the parent Image Track id and size, + * the parent group id and size, and the image id and size + * + * @param track_id + * @param track_id_size + * @param scene_id + * @param scene_id_size + * @param item_id + * @param item_id_size + */ +void +ImageFrameSocketHandler::decompose_imageframe_item_desc(const char* msg, int& position, std::string& track_id, + int& track_id_size, std::string& scene_id, int& scene_id_size, std::string& item_id, int& item_id_size) +{ + // get the track Id size + track_id_size = atoi(get_message_part(position,ardourvis::TEXT_SIZE_CHARS,msg).c_str()) ; + position += ardourvis::TEXT_SIZE_CHARS ; + + // get the track id + track_id = get_message_part(position,track_id_size,msg) ; + position += track_id_size ; + + // get the track Id size + scene_id_size = atoi(get_message_part(position,ardourvis::TEXT_SIZE_CHARS,msg).c_str()) ; + position += ardourvis::TEXT_SIZE_CHARS ; + + // get the scene id + scene_id = get_message_part(position,scene_id_size,msg) ; + position += scene_id_size ; + + // get the item id size + item_id_size = atoi(get_message_part(position,ardourvis::TEXT_SIZE_CHARS,msg).c_str()) ; + position += ardourvis::TEXT_SIZE_CHARS ; + + // get the item id + item_id = get_message_part(position,item_id_size,msg) ; + position += item_id_size ; +} + +/** + * Compose a description of the specified image frame view + * The description consists of the parent track name size and name, + * the parent group name size and name, and the item name size and name + * + * @param ifv the item to compose a description of + * @param buffer the buffer to write the description + */ +void +ImageFrameSocketHandler::compose_imageframe_item_desc(ImageFrameView* ifv, std::ostringstream& buffer) +{ + buffer << std::setw(3) << ifv->get_time_axis_group()->get_view().trackview().name().length() ; + buffer << ifv->get_time_axis_group()->get_view().trackview().name() ; + + // add the parent scene + buffer << std::setw(3) << ifv->get_time_axis_group()->get_group_name().length() ; + buffer << ifv->get_time_axis_group()->get_group_name() ; + + // add the ImageFrameItem id length and Id + buffer << setw(3) << ifv->get_item_name().length() ; + buffer << ifv->get_item_name() ; +} + +/** + * Compose a description of the specified marker view + * The description consists of the parent track name size and name, + * and the item name size and name + * + * @param mv the item to compose a description of + * @param buffer the buffer to write the description + */ +void +ImageFrameSocketHandler::compose_marker_item_desc(MarkerView* mv, std::ostringstream& buffer) +{ + MarkerTimeAxis* mta = dynamic_cast(&mv->get_time_axis_view()) ; + + if(!mta) + { + return ; + } + + buffer << std::setw(3) << mta->name().length() ; + buffer << mta->name() ; + + buffer << std::setw(3) << mv->get_item_name().length() ; + buffer << mv->get_item_name() ; +} + + +/** + * Returns the ImageFrameView from the specified description + * The errcode parameter is used to indicate the item which caused + * an error on failure of this method + * 0 = success + * 1 = the track item was not found + * 2 = the group item was not found + * 3 = the imageframe item was not found + * + * @paran track_id the track on which the item is placed + * @param group_id the group in which the item is a member + * @param item_id the id of the item + * @param int32_t reference used for error codes on failure + * @param errmsg populated with a description of the error on failure + * @return the described item on success, 0 otherwise + */ +ImageFrameView* +ImageFrameSocketHandler::get_imageframe_view_from_desc(const std::string& track_id, const std::string& group_id, const std::string& item_id, int& errcode, std::string& errmsg) +{ + ImageFrameView* item = 0 ; + + // get the named time axis + ImageFrameTimeAxis* ifta = dynamic_cast(thePublicEditor.get_named_time_axis(track_id)) ; + + if(!ifta) + { + errcode = 1 ; + errmsg = std::string("Image Frame Time Axis Not Found: ").append(track_id) ; + } + else + { + // get the parent scene + ImageFrameTimeAxisGroup* iftag = ifta->get_view()->get_named_imageframe_group(group_id) ; + if(!iftag) + { + errcode = 2 ; + errmsg = std::string("Image Frame Group Not Found: ").append(group_id) ; + } + else + { + ImageFrameView* ifv = iftag->get_named_imageframe_item(item_id) ; + if(!ifv) + { + errcode = 3 ; + errmsg = std::string("Image Frame Item Not Found: ").append(item_id) ; + } + else + { + // yay!! + item = ifv ; + errcode = 0 ; + } + } + } + + return(item) ; +} + +//---------------------------------------------------------------------------------------// +// Convenince Message Send Methods + +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + +/** + * Sends a message throught the socket + * + * @param msg the message to send + * @return the return value of the socket call + */ +int +ImageFrameSocketHandler::send_message(const std::string& msg) +{ + //std::cout << "Sending Message [" << msg << "]\n" ; + int retcode = ::send(theArdourToCompositorSocket, msg.c_str(), msg.length(), MSG_NOSIGNAL) ; + + return(retcode) ; +} + +/** + * Reads a message from the Socket + * + * @param msg a string to populate with the received message + * @return the return value from the socket call + */ +int +ImageFrameSocketHandler::read_message(std::string& msg) +{ + char buf[ardourvis::MAX_MSG_SIZE + 1] ; + memset(buf, 0, (ardourvis::MAX_MSG_SIZE + 1)) ; + + msg = "" ; + int retcode = ::recv(theArdourToCompositorSocket, buf, ardourvis::MAX_MSG_SIZE, 0) ; + + msg = buf ; + //std::cout << "Received Message [" << msg << "]\n" ; + + return(retcode) ; +} + + +/** + * Convenience method to compose and send a success messasge back to the Image Compositor + * + */ +void +ImageFrameSocketHandler::send_return_success() +{ + send_message(ardourvis::RETURN_TRUE) ; +} + +/** + * Convenience method to compose and send a failure messasge back to the Image Compositor + * + * @param msg the failure message + */ +void +ImageFrameSocketHandler::send_return_failure(const std::string& msg) +{ + std::ostringstream buf ; + buf << std::setfill('0') ; + buf << ardourvis::RETURN_FALSE ; + buf << std::setw(3) << msg.length(); ; + buf << msg ; + + send_message(buf.str()) ; +} diff --git a/gtk2_ardour/imageframe_socket_handler.h b/gtk2_ardour/imageframe_socket_handler.h new file mode 100644 index 0000000000..93a82b63bb --- /dev/null +++ b/gtk2_ardour/imageframe_socket_handler.h @@ -0,0 +1,705 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_imageframe_socket_handler_h__ +#define __ardour_gtk_imageframe_socket_handler_h__ + +#include +#include +#include +#include "editor.h" +#include "ardour_image_compositor_socket.h" + +class TimeAxisViewItem ; +class ImageFrameView ; +class MarkerView ; +class ImageFrameTimeAxisGroup ; + +/** + * ImageFrameSocketHandler defines the handler between Ardour and an Image Compositor + * As this is purely visual, we do all processing within the main gtk loop via + * message passing through a socket. + * + */ +class ImageFrameSocketHandler : public SigC::Object +{ + public: + /** + * Constructs a new ImageFrameSocketHandler to handle communication between Ardour and the Image Compositor + * + * @param ed the PublicEditor + */ + ImageFrameSocketHandler(PublicEditor& ed) ; + + /** + * Descructor + * this will shutdown the socket if open + */ + virtual ~ImageFrameSocketHandler() ; + + /** + * Returns the instance of the ImageFrameSocketHandler + * the instance should first be created with createInstance + * + * @return the instance of the ImageFrameSocketHandler + */ + static ImageFrameSocketHandler* get_instance() ; + + /** + * call back to handle doing the processing work + * This method is added to the gdk main loop and called when there is data + * upon the socket. + * + */ + static void image_socket_callback(void *arg, int32_t fd, GdkInputCondition cond) ; + + /** + * Attempt to connect to the image compositor on the specified host and port + * + * @param hostIp the ip address of the image compositor host + * @param port the oprt number to attemp the connection on + * @return true if the connection was a succees + * false otherwise + */ + bool connect(std::string hostIp, int32_t port) ; + + /** + * Closes the connection to th Image Compositor + * + */ + void close_connection() ; + /** + * Returns true if this ImagFrameSocketHandler is currently connected to rthe image compositor + * + * @return true if connected to the image compositor + */ + bool is_connected() ; + + /** + * Sets the tag used to describe this input within gtk + * this is returned when gdk_input_add is called and is required to remove the input + * + * @param tag the gdk input tag of this input + */ + void set_gdk_input_tag(int tag) ; + + /** + * Returns the gdk input tag of this input + * + * @return the gdk input tag of this input + * @see setGdkInputTag + */ + int get_gdk_input_tag() ; + + + /** + * Returns the socket file descriptor + * + * @return the Sockt file descriptor + */ + int get_socket_descriptor() ; + + + //---------------------------------------------------------------------------------------// + // Handle Sending messages to the Image Compositor + + //---------------------------- + // ImageFrameTimeAxis Messages + + /** + * Sends a message stating that the named image frame time axis has been removed + * + * @param track_id the unique id of the removed image frame time axis + * @param src the identity of the object that initiated the change + */ + void send_imageframe_time_axis_removed(std::string track_id, void* src) ; + + /** + * Sends a message indicating that an ImageFrameTimeAxis has been renamed + * + * @param new_id the new name, or Id, of the track + * @param old_id the old name, or Id, of the track + * @param src the identity of the object that initiated the change + * @param time_axis the time axis that has changed + */ + void send_imageframe_time_axis_renamed(std::string new_id, std::string old_id, void* src, ImageFrameTimeAxis* time_axis) ; + + //------------------------ + // MarkerTimeAxis Messages + + /** + * Sends a message stating that the named marker time axis has been removed + * + * @param track_id the unique id of the removed image frame time axis + * @param src the identity of the object that initiated the change + */ + void send_marker_time_axis_removed(std::string track_id, void* src) ; + + /** + * Sends a message indicating that an MarkerTimeAxis has been renamed + * + * @param new_id the new name, or Id, of the track + * @param old_id the old name, or Id, of the track + * @param src the identity of the object that initiated the change + * @param time_axis the time axis that has changed + */ + void send_marker_time_axis_renamed(std::string new_id, std::string old_id, void* src, MarkerTimeAxis* time_axis) ; + + + //--------------------------------- + // ImageFrameTimeAxisGroup Messages + + /** + * Sends a message stating that the group has been removed + * + * @param group_id the unique id of the removed image frame time axis + * @param src the identity of the object that initiated the change + * @param group the group that has changed + */ + void send_imageframe_time_axis_group_removed(std::string group_id, void* src, ImageFrameTimeAxisGroup* group) ; + + /** + * Send a message indicating that an ImageFrameTimeAxisGroup has been renamed + * + * @param new_id the new name, or Id, of the group + * @param old_id the old name, or Id, of the group + * @param src the identity of the object that initiated the change + * @param group the group that has changed + */ + void send_imageframe_time_axis_group_renamed(std::string new_id, std::string old_id, void* src, ImageFrameTimeAxisGroup* group) ; + + + //--------------------------------- + // ImageFrameView Messages + + /** + * Send an Image Frame View Item position changed message + * + * @param pos the new position value + * @param src the identity of the object that initiated the change + * @param item the time axis item whos position has changed + */ + void send_imageframe_view_position_change(jack_nframes_t pos, void* src, ImageFrameView* item) ; + + /** + * Send a Image Frame View item duration changed message + * + * @param dur the the new duration value + * @param src the identity of the object that initiated the change + * @param item the item which has had a duration change + */ + void send_imageframe_view_duration_change(jack_nframes_t dur, void* src, ImageFrameView* item) ; + + /** + * Send a message indicating that an ImageFrameView has been renamed + * + * @param item the ImageFrameView which has been renamed + * @param src the identity of the object that initiated the change + * @param item the renamed item + */ + void send_imageframe_view_renamed(std::string new_id, std::string old_id, void* src, ImageFrameView* item) ; + + /** + * Send a message indicating that an ImageFrameView item has been removed message + * + * @param item_id the id of the item that was removed + * @param src the identity of the object that initiated the change + * @param item the removed item + */ + void send_imageframe_view_removed(std::string item_id, void* src, ImageFrameView* item) ; + + //--------------------------------- + // MarkerView Messages + + /** + * Send a Marker View Item position changed message + * + * @param pos the new position value + * @param src the identity of the object that initiated the change + * @param item the time axis item whos position has changed + */ + void send_marker_view_position_change(jack_nframes_t pos, void* src, MarkerView* item) ; + + /** + * Send a Marker View item duration changed message + * + * @param dur the new duration value + * @param src the identity of the object that initiated the change + * @param item the time axis item whos position has changed + */ + void send_marker_view_duration_change(jack_nframes_t dur, void* src, MarkerView* item) ; + + /** + * Send a message indicating that a MarkerView has been renamed + * + * @param new_id the new_id of the object + * @param old_id the old_id of the object + * @param src the identity of the object that initiated the change + * @param item the MarkerView which has been renamed + */ + void send_marker_view_renamed(std::string new_id, std::string old_id, void* src, MarkerView* item) ; + + /** + * Send a message indicating that a MarkerView item has been removed message + * + * @param item_id the id of the item that was removed + * @param src the identity of the object that initiated the change + * @param item the MarkerView which has been removed + */ + void send_marker_view_removed(std::string item_id, void* src, MarkerView* item) ; + + + //---------------------------------------------------------------------------------------// + // Emitted Signals + + /** Emitted if the socket connection is shutdown at the other end */ + SigC::Signal0 CompositorSocketShutdown ; + + /** Emitted as a generic error is captured from the socket connection to the animatic compositor */ + SigC::Signal0 CompositorSocketError ; + + + protected: + + + private: + /* I dont like friends :-( */ + friend class Editor; + + /** + * Create an new instance of the ImageFrameSocketHandler, if one does not already exist + * + * @param ed the Ardour PublicEditor + */ + static ImageFrameSocketHandler* create_instance(PublicEditor& ed) ; + + //---------------------------------------------------------------------------------------// + // Message breakdown ie avoid a big if...then...else + + /** + * Handle insert item requests + * + * @param msg the received message + */ + void handle_insert_message(const char* msg) ; + + /** + * Handle remove item requests + * + * @param msg the received message + */ + void handle_remove_message(const char* msg) ; + + /** + * Handle rename item requests + * + * @param msg the received message + */ + void handle_rename_message(const char* msg) ; + + /** + * Handle a request for session information + * + * @param msg the received message + */ + void handle_request_data(const char* msg) ; + + /** + * Handle the update of a particular item + * + * @param msg the received message + */ + void handle_item_update_message(const char* msg) ; + + /** + * Handle the selection of an Item + * + * @param msg the received message + */ + void handle_item_selected(const char* msg) ; + + /** + * Handle s session action message + * + * @param msg the received message + */ + void handle_session_action(const char* msg) ; + + //---------------------------------------------------------------------------------------// + // handlers for specific insert procedures + + /** + * Handle the insertion of a new ImaegFrameTimeAxis + * + * @param msg the received message + */ + void handle_insert_imageframe_time_axis(const char* msg) ; + + /** + * Handle the insertion of a new MarkerTimeAxis + * + * @param msg the received message + */ + void handle_insert_marker_time_axis(const char* msg) ; + + /** + * Handle the insertion of a time axis group (a scene) + * + * @param msg the received message + */ + void handle_insert_imageframe_group(const char* msg) ; + + /** + * Handle the insertion of a new ImageFrameItem + * + * @param msg the received message + */ + void handle_insert_imageframe_view(const char* msg) ; + + /** + * Handle the insertion of a new MarkerItem + * + * @param msg the received message + */ + void handle_insert_marker_view(const char* msg) ; + + //---------------------------------------------------------------------------------------// + // handlers for specific removal procedures + + /** + * Handle the removal of an ImageTimeAxis + * + * @param msg the received message + */ + void handle_remove_imageframe_time_axis(const char* msg) ; + + /** + * Handle the removal of an MarkerTimeAxis + * + * @param msg the received message + */ + void handle_remove_marker_time_axis(const char* msg) ; + + /** + * Handle the removal of an ImageFrameTimeAxisGroup + * + * @param msg the received message + */ + void handle_remove_imageframe_time_axis_group(const char* msg) ; + + /** + * Handle the removal of an ImageFrameItem + * + * @param msg the received message + */ + void handle_remove_imageframe_view(const char* msg) ; + + /** + * Handle the removal of an MarkerItem + * + * @param msg the received message + */ + void handle_remove_marker_view(const char* msg) ; + + //---------------------------------------------------------------------------------------// + // handlers for the specific rename procedures + + /** + * Handle the renaming of an ImageTimeAxis + * + * @param msg the received message + */ + void handle_rename_imageframe_time_axis(const char* msg) ; + + /** + * Handle the renaming of an MarkerTimeAxis + * + * @param msg the received message + */ + void handle_rename_marker_time_axis(const char* msg) ; + + /** + * Handle the renaming of an ImageFrameItem + * + * @param msg the received message + */ + void handle_rename_imageframe_time_axis_group(const char* msg) ; + + /** + * Handle the renaming of an ImageFrameItem + * + * @param msg the received message + */ + void handle_rename_imageframe_view(const char* msg) ; + + /** + * Handle the renaming of an Marker + * + * @param msg the received message + */ + void handle_rename_marker_view(const char* msg) ; + + //---------------------------------------------------------------------------------------// + // handlers for data request + + /** + * Handle a request for the sessnio naem fo the current session + * We return a failure state if no session is open + * + * @param msg the received message + */ + void handle_session_name_request(const char* msg) ; + + + //---------------------------------------------------------------------------------------// + // handlers for specific item update changes + + /** + * Handle ImageFrameView positional changes + * + * @param msg the received message + */ + void handle_imageframe_view_position_update(const char* msg) ; + + /** + * Handle ImageFrameView Duration changes + * + * @param msg the received message + */ + void handle_imageframe_view_duration_update(const char* msg) ; + + /** + * Handle ImageFrameView Position Lock Constraint changes + * + * @param msg the received message + */ + void handle_imageframe_position_lock_update(const char* msg) ; + + /** + * Handle ImageFrameView Maximum Duration changes + * + * @param msg the received message + */ + void handle_imageframe_view_max_duration_update(const char* msg) ; + + /** + * Handle image frame max duration enable constraint changes + * + * @param msg the received message + */ + void handle_imageframe_view_max_duration_enable_update(const char* msg) ; + + /** + * Handle ImageFrameView Minimum Duration changes + * + * @param msg the received message + */ + void handle_imageframe_view_min_duration_update(const char* msg) ; + + /** + * Handle image frame min duration enable constraint changes + * + * @param msg the received message + */ + void handle_imageframe_view_min_duration_enable_update(const char* msg) ; + + + /** + * Handle MarkerView position changes + * + * @param msg the received message + */ + void handle_marker_view_position_update(const char* msg) ; + + /** + * Handle MarkerView duration changes + * + * @param msg the received message + */ + void handle_marker_view_duration_update(const char* msg) ; + + /** + * Handle MarkerView Position Lock Constraint changes + * + * @param msg the received message + */ + void handle_marker_view_position_lock_update(const char* msg) ; + + /** + * Handle MarkerView maximum duration changes + * + * @param msg the received message + */ + void handle_marker_view_max_duration_update(const char* msg) ; + + /** + * Handle MarkerView minimum duration changes + * + * @param msg the received message + */ + void handle_marker_view_min_duration_update(const char* msg) ; + + + + //---------------------------------------------------------------------------------------// + // handlers for Session Actions + + /** + * Handle the opening of a named audio session + * + * @param msg the received message + */ + void handle_open_session(const char* msg) ; + + /** + * Handle the closing of a named audio session + * + * @param msg the received message + */ + void handle_closed_session(const char* msg) ; + + //---------------------------------------------------------------------------------------// + // handlers for the shutdown of the Image Compositor + + /** + * Handle the shutdown message from the image compositor + * + * @param msg the received message + */ + void handle_shutdown(const char* msg) ; + + + //---------------------------------------------------------------------------------------// + // convenince methods to break up messages + + /** + * Returns part of the received message as a std::string + * + * @param start the start character + * @param num_chars the number of characters to read + * @param the message to break apart + * @return the sub string of the message + */ + std::string get_message_part(int start, int32_t num_chars, const char* msg) ; + + + /** + * break up am image item description message + * we break the mesage up into the parent Image Track id and size, + * the parent group id and size, and the image id and size + * + * @param track_id + * @param track_id_size + * @param scene_id + * @param scene_id_size + * @param item_id + * @param item_id_size + */ + void decompose_imageframe_item_desc(const char* msg, int& position, std::string& track_id, int& track_id_size, std::string& scene_id, int& scene_id_size, std::string& item_id, int& item_id_size) ; + + /** + * Compose a description of the specified image frame view + * The description consists of the parent track name size and name, + * the parent group name size and name, and the item name size and name + * + * @param ifv the item to compose a description of + * @param buffer the buffer to write the description + */ + void compose_imageframe_item_desc(ImageFrameView* ifv, std::ostringstream& buffer) ; + + /** + * Compose a description of the specified marker view + * The description consists of the parent track name size and name, + * and the item name size and name + * + * @param mv the item to compose a description of + * @param buffer the buffer to write the description + */ + void compose_marker_item_desc(MarkerView* mv, std::ostringstream& buffer) ; + + + /** + * Returns the ImageFrameView from the specified description + * The errcode parameter is used to indicate the item which caused + * an error on failure of this method + * 0 = suces + * 1 = the track item was not found + * 2 = the group item was not found + * 3 = the imageframe item was not found + * + * @paran track_id the track on which the item is placed + * @param group_id the group in which the item is a member + * @param item_id the id of the item + * @param int32_t reference used for error codes on failure + * @param errmsg populated with a description of the error on failure + * @return the described item on success, 0 otherwise + */ + ImageFrameView* get_imageframe_view_from_desc(const std::string& track_id, const std::string& group_ud, const std::string& item_id, int& errcode, std::string& errmsg) ; + + //---------------------------------------------------------------------------------------// + // Convenince Message Send Methods + + /** + * Sends a message throught the socket + * + * @param msg the message to send + * @return the return value of the socket call + */ + int send_message(const std::string& msg) ; + + /** + * Reads a message from the Socket + * + * @param msg a string to populate with the received message + * @return the return value from the socket call + */ + int read_message(std::string& msg) ; + + /** + * Convenience method to compose and send a success messasge back to the Image Compositor + * + */ + void send_return_success() ; + + /** + * Convenience method to compose and send a failure messasge back to the Image Compositor + * + * @param msg the failure message + */ + void send_return_failure(const std::string& msg) ; + + //---------------------------------------------------------------------------------------// + // Memebr Data + + /** Our instance of the socket handler, singleton */ + static ImageFrameSocketHandler* _instance ; + + /** The Ardour PublicEditor */ + PublicEditor& thePublicEditor ; + + /** the socket file descriptor */ + int theArdourToCompositorSocket ; + + /** This stores the 'tag' returned from gdk_input_add, which is required for removing the input */ + int theGdkInputTag ; + +} ; /* class ImageFrameSocketHandler */ + +#endif /* __ardour_gtk_imageframe_socket_handler_h__ */ diff --git a/gtk2_ardour/imageframe_time_axis.cc b/gtk2_ardour/imageframe_time_axis.cc new file mode 100644 index 0000000000..51325ca38f --- /dev/null +++ b/gtk2_ardour/imageframe_time_axis.cc @@ -0,0 +1,440 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include + +#include +#include + +#include +#include + +#include "public_editor.h" +#include "imageframe_time_axis.h" +#include "canvas-simplerect.h" +#include "enums.h" +#include "imageframe_time_axis_view.h" +#include "imageframe_time_axis_group.h" +#include "marker_time_axis_view.h" +#include "imageframe_view.h" +#include "marker_time_axis.h" +#include "marker_view.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace ARDOUR ; +using namespace SigC ; +using namespace Gtk ; + +/** + * Constructs a new ImageFrameTimeAxis. + * + * @param track_id the track name/id + * @param ed the PublicEditor + * @param sess the current session + * @param canvas the parent canvas item + */ +ImageFrameTimeAxis::ImageFrameTimeAxis(std::string track_id, PublicEditor& ed, ARDOUR::Session& sess, Widget *canvas) + : AxisView(sess), + VisualTimeAxis(track_id, ed, sess, canvas) +{ + _color = unique_random_color() ; + + selection_group = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_display), gtk_canvas_group_get_type (), NULL) ; + gtk_canvas_item_hide(selection_group) ; + + // intialize our data items + _marked_for_display = true; + y_position = -1 ; + name_prompter = 0 ; + + /* create our new image frame view */ + view = new ImageFrameTimeAxisView(*this) ; + + /* create the Image Frame Edit Menu */ + create_imageframe_menu() ; + + // set the initial time axis text label + label_view() ; + + // set the initial height of this time axis + set_height(Normal) ; +} + +/** + * Destructor + * Responsible for destroying any child image items that may have been added to thie time axis + */ +ImageFrameTimeAxis::~ImageFrameTimeAxis () +{ + GoingAway() ; /* EMIT_SIGNAL */ + + // Destroy all the marker views we may have associaited with this TimeAxis + for(MarkerTimeAxisList::iterator iter = marker_time_axis_list.begin(); iter != marker_time_axis_list.end(); ++iter) + { + MarkerTimeAxis* mta = *iter ; + MarkerTimeAxisList::iterator next = iter ; + next++ ; + + marker_time_axis_list.erase(iter) ; + + delete mta ; + mta = 0 ; + + iter = next ; + } + + if(image_action_menu) + { + delete image_action_menu ; + image_action_menu = 0 ; + } + + for(list::iterator i = free_selection_rects.begin(); i != free_selection_rects.end(); ++i) + { + gtk_object_destroy (GTK_OBJECT((*i)->rect)); + gtk_object_destroy (GTK_OBJECT((*i)->start_trim)); + gtk_object_destroy (GTK_OBJECT((*i)->end_trim)); + } + + for(list::iterator i = used_selection_rects.begin(); i != used_selection_rects.end(); ++i) + { + gtk_object_destroy (GTK_OBJECT((*i)->rect)); + gtk_object_destroy (GTK_OBJECT((*i)->start_trim)); + gtk_object_destroy (GTK_OBJECT((*i)->end_trim)); + } + + if (selection_group) + { + gtk_object_destroy (GTK_OBJECT (selection_group)); + selection_group = 0 ; + } + + // Destroy our Axis View helper + if(view) + { + delete view ; + view = 0 ; + } +} + +//---------------------------------------------------------------------------------------// +// ui methods & data + +/** + * Sets the height of this TrackView to one of ths TrackHeghts + * + * @param h the TrackHeight value to set + */ +void +ImageFrameTimeAxis::set_height (TrackHeight h) +{ + VisualTimeAxis::set_height(h) ; + + // tell out view helper of the change too + if(view != 0) + { + view->set_height((double) height) ; + } + + // tell those interested that we have had our height changed + gui_changed("track_height",(void*)0); /* EMIT_SIGNAL */ +} + +/** + * Sets the number of samples per unit that are used. + * This is used to determine the siezes of items upon this time axis + * + * @param spu the number of samples per unit + */ +void +ImageFrameTimeAxis::set_samples_per_unit(double spu) +{ + TimeAxisView::set_samples_per_unit (editor.get_current_zoom()); + + if(view) { + view->set_samples_per_unit(spu) ; + } +} + + +/** + * Returns the available height for images to be drawn onto + * + * @return the available height for an image item to be drawn onto + */ +int +ImageFrameTimeAxis::get_image_display_height() +{ + return(height - (gint)TimeAxisViewItem::NAME_HIGHLIGHT_SIZE) ; +} + + +/** + * Show the popup edit menu + * + * @param button the mouse button pressed + * @param time when to show the popup + * @param clicked_imageframe the ImageFrameItem that the event ocured upon, or 0 if none + * @param with_item true if an item has been selected upon the time axis, used to set context menu + */ +void +ImageFrameTimeAxis::popup_imageframe_edit_menu(int button, int32_t time, ImageFrameView* clicked_imageframe, bool with_item) +{ + if (!imageframe_menu) + { + create_imageframe_menu() ; + } + + if(with_item) + { + imageframe_item_menu->set_sensitive(true) ; + } + else + { + imageframe_item_menu->set_sensitive(false) ; + } + + imageframe_menu->popup(button,time) ; +} + +/** + * convenience method to select a new track color and apply it to the view and view items + * + */ +void +ImageFrameTimeAxis::select_track_color() +{ + if (choose_time_axis_color()) + { + if (view) + { + view->apply_color (_color) ; + } + } +} + +/** + * Handles the building of the popup menu + */ +void +ImageFrameTimeAxis::build_display_menu() +{ + using namespace Menu_Helpers; + + /* get the size menu ready */ + + build_size_menu(); + + /* prepare it */ + + TimeAxisView::build_display_menu () ; + + /* now fill it with our stuff */ + + MenuList& items = display_menu->items(); + + items.push_back (MenuElem (_("Rename"), slot(*this, &ImageFrameTimeAxis::start_time_axis_rename))); + + image_action_menu = new Menu() ; + image_action_menu->set_name ("ArdourContextMenu"); + MenuList image_items = image_action_menu->items() ; + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Height"), *size_menu)); + items.push_back (MenuElem (_("Color"), slot(*this, &ImageFrameTimeAxis::select_track_color))); + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Remove"), bind(slot(*this, &VisualTimeAxis::remove_this_time_axis), (void*)this))) ; +} + +/** + * handles the building of the ImageFrameView sub menu + */ +void +ImageFrameTimeAxis::create_imageframe_menu() +{ + using namespace Menu_Helpers; + + imageframe_menu = manage(new Menu) ; + imageframe_menu->set_name ("ArdourContextMenu"); + MenuList& items = imageframe_menu->items(); + + imageframe_item_menu = manage(new Menu) ; + imageframe_item_menu->set_name ("ArdourContextMenu"); + MenuList& imageframe_sub_items = imageframe_item_menu->items() ; + + /* duration menu */ + Menu* duration_menu = manage(new Menu) ; + duration_menu->set_name ("ArdourContextMenu"); + MenuList& duration_items = duration_menu->items() ; + + if(view) + { + duration_items.push_back(MenuElem (_("0.5 seconds"), bind (slot (view, &ImageFrameTimeAxisView::set_imageframe_duration_sec), 0.5))) ; + duration_items.push_back(MenuElem (_("1 seconds"), bind (slot (view, &ImageFrameTimeAxisView::set_imageframe_duration_sec), 1.0))) ; + duration_items.push_back(MenuElem (_("1.5 seconds"), bind (slot (view, &ImageFrameTimeAxisView::set_imageframe_duration_sec), 1.5))) ; + duration_items.push_back(MenuElem (_("2 seconds"), bind (slot (view, &ImageFrameTimeAxisView::set_imageframe_duration_sec), 2.0))) ; + duration_items.push_back(MenuElem (_("2.5 seconds"), bind (slot (view, &ImageFrameTimeAxisView::set_imageframe_duration_sec), 2.5))) ; + duration_items.push_back(MenuElem (_("3 seconds"), bind (slot (view, &ImageFrameTimeAxisView::set_imageframe_duration_sec), 3.0))) ; + //duration_items.push_back(SeparatorElem()) ; + //duration_items.push_back(MenuElem (_("custom"), slot (*this, &ImageFrameTimeAxis::set_imageframe_duration_custom))) ; + } + + imageframe_sub_items.push_back(MenuElem(_("Duration (sec)"), *duration_menu)) ; + + imageframe_sub_items.push_back(SeparatorElem()) ; + if(view) + { + imageframe_sub_items.push_back(MenuElem (_("Remove Frame"), bind(slot (view, &ImageFrameTimeAxisView::remove_selected_imageframe_item), (void*)this))) ; + } + + items.push_back(MenuElem(_("Image Frame"), *imageframe_item_menu)) ; + items.push_back(MenuElem (_("Rename Track"), slot (*this,&ImageFrameTimeAxis::start_time_axis_rename))) ; + + imageframe_menu->show_all() ; +} + + + + +//---------------------------------------------------------------------------------------// +// Marker Time Axis Methods + +/** + * Add a MarkerTimeAxis to the ilst of MarkerTimeAxis' associated with this ImageFrameTimeAxis + * + * @param marker_track the MarkerTimeAxis to add + * @param src the identity of the object that initiated the change + * @return true if the addition was a success, + * false otherwise + */ +bool +ImageFrameTimeAxis::add_marker_time_axis(MarkerTimeAxis* marker_track, void* src) +{ + bool ret = false ; + + if(get_named_marker_time_axis(marker_track->name()) != 0) + { + ret = false ; + } + else + { + marker_time_axis_list.push_back(marker_track) ; + marker_track->GoingAway.connect(bind(slot(*this, &ImageFrameTimeAxis::remove_time_axis_view), marker_track, (void*)this)); + + MarkerTimeAxisAdded(marker_track, src) ; /* EMIT_SIGNAL */ + ret = true ; + } + + return(ret) ; +} + +/** + * Returns the named MarkerTimeAxis associated with this ImageFrameTimeAxis + * + * @param track_id the track_id of the MarkerTimeAxis to search for + * @return the named markerTimeAxis, or 0 if the named MarkerTimeAxis is not associated with this ImageFrameTimeAxis + */ +MarkerTimeAxis* +ImageFrameTimeAxis::get_named_marker_time_axis(std::string track_id) +{ + MarkerTimeAxis* mta = 0 ; + + for (MarkerTimeAxisList::iterator i = marker_time_axis_list.begin(); i != marker_time_axis_list.end(); ++i) + { + if (((MarkerTimeAxis*)*i)->name() == track_id) + { + mta = ((MarkerTimeAxis*)*i) ; + break ; + } + } + return(mta) ; +} + +/** + * Removes the named markerTimeAxis from those associated with this ImageFrameTimeAxis + * + * @param track_id the track id of the MarkerTimeAxis to remove + * @param src the identity of the object that initiated the change + * @return the removed MarkerTimeAxis + */ +MarkerTimeAxis* +ImageFrameTimeAxis::remove_named_marker_time_axis(std::string track_id, void* src) +{ + MarkerTimeAxis* mta = 0 ; + + for(MarkerTimeAxisList::iterator i = marker_time_axis_list.begin(); i != marker_time_axis_list.end(); ++i) + { + if (((MarkerTimeAxis*)*i)->name() == track_id) + { + mta = ((MarkerTimeAxis*)*i) ; + + // the iterator is invalid after this call, so we can no longer use it as is. + marker_time_axis_list.erase(i) ; + + MarkerTimeAxisRemoved(mta->name(), src) ; /* EMIT_SIGNAL */ + break ; + } + } + + return(mta) ; +} + +/** + * Removes the specified MarkerTimeAxis from the list of MarkerTimaAxis associated with this ImageFrameTimeAxis + * Note that the MarkerTimeAxis is not deleted, only removed from the list os associated tracks + * + * @param mta the TimeAxis to remove + * @param src the identity of the object that initiated the change + */ +void +ImageFrameTimeAxis::remove_time_axis_view(MarkerTimeAxis* mta, void* src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameTimeAxis::remove_time_axis_view), mta, src)); + + MarkerTimeAxisList::iterator i; + if((i = find (marker_time_axis_list.begin(), marker_time_axis_list.end(), mta)) != marker_time_axis_list.end()) + { + // note that we dont delete the object itself, we just remove it from our list + marker_time_axis_list.erase(i) ; + + MarkerTimeAxisRemoved(mta->name(), src) ; /* EMIT_SIGNAL */ + } +} + + +//---------------------------------------------------------------------------------------// +// Parent/Child helper object accessors + +/** + * Returns the view helper of this TimeAxis + * + * @return the view helper of this TimeAxis + */ +ImageFrameTimeAxisView* +ImageFrameTimeAxis::get_view() +{ + return(view) ; +} diff --git a/gtk2_ardour/imageframe_time_axis.h b/gtk2_ardour/imageframe_time_axis.h new file mode 100644 index 0000000000..dfbb0bd72f --- /dev/null +++ b/gtk2_ardour/imageframe_time_axis.h @@ -0,0 +1,200 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_imageframe_time_axis_h__ +#define __ardour_imageframe_time_axis_h__ + +#include +#include + +#include "ardour_dialog.h" +#include "enums.h" +#include "time_axis_view.h" +#include +#include "visual_time_axis.h" + +namespace ARDOUR +{ + class Session ; +} + +class PublicEditor ; +class ImageFrameView ; +class ImageFrameTimeAxisView ; +class MarkersTimeAxisView ; +class MarkerTimeAxis; + +/** + * ImageFrameTimeAxis defines a visual time axis view for holding and arranging image items. + * + */ +class ImageFrameTimeAxis : public VisualTimeAxis +{ + public: + //---------------------------------------------------------------------------------------// + // Constructor / Desctructor + + /** + * Constructs a new ImageFrameTimeAxis. + * + * @param track_id the track name/id + * @param ed the PublicEditor + * @param sess the current session + * @param canvas the parent canvas item + */ + ImageFrameTimeAxis(std::string track_id, PublicEditor& ed, ARDOUR::Session& sess, Gtk::Widget *canvas) ; + + /** + * Destructor + * Responsible for destroying any child image items that may have been added to thie time axis + */ + virtual ~ImageFrameTimeAxis() ; + + //---------------------------------------------------------------------------------------// + // ui methods & data + + /** + * Sets the height of this TrackView to one of ths TrackHeghts + * + * @param h the TrackHeight value to set + */ + virtual void set_height(TimeAxisView::TrackHeight) ; + + /** + * Sets the number of samples per unit that are used. + * This is used to determine the siezes of items upon this time axis + * + * @param spu the number of samples per unit + */ + virtual void set_samples_per_unit(double spu) ; + + /** + * Returns the available height for images to be drawn onto + * + * @return the available height for an image item to be drawn onto + */ + int get_image_display_height() ; + + + /** + * Show the popup edit menu + * + * @param button the mouse button pressed + * @param time when to show the popup + * @param clicked_imageframe the ImageFrameItem that the event ocured upon, or 0 if none + * @param with_item true if an item has been selected upon the time axis, used to set context menu + */ + void popup_imageframe_edit_menu(int button, int32_t time, ImageFrameView* clicked_imageframe, bool with_item) ; + + + //---------------------------------------------------------------------------------------// + // Marker Time Axis Methods + + /** + * Add a MarkerTimeAxis to the ilst of MarkerTimeAxis' associated with this ImageFrameTimeAxis + * + * @param marker_track the MarkerTimeAxis to add + * @param src the identity of the object that initiated the change + * @return true if the addition was a success, + * false otherwise + */ + bool add_marker_time_axis(MarkerTimeAxis* marker_track, void* src) ; + + /** + * Returns the named MarkerTimeAxis associated with this ImageFrameTimeAxis + * + * @param track_id the track_id of the MarkerTimeAxis to search for + * @return the named markerTimeAxis, or 0 if the named MarkerTimeAxis is not associated with this ImageFrameTimeAxis + */ + MarkerTimeAxis* get_named_marker_time_axis(std::string track_id) ; + + /** + * Removes the named markerTimeAxis from those associated with this ImageFrameTimeAxis + * + * @param track_id the track id of the MarkerTimeAxis to remove + * @param src the identity of the object that initiated the change + * @return the removed MarkerTimeAxis + */ + MarkerTimeAxis* remove_named_marker_time_axis(std::string track_id, void* src) ; + + /** + * Removes tav from the list of MarkerTimaAxis associated with this ImageFrameTimeAxis + * + * @param tav the TimeAxis to remove + * @param src the identity of the object that initiated the change + */ + void remove_time_axis_view(MarkerTimeAxis* tav, void* src) ; + + + //---------------------------------------------------------------------------------------// + // Parent/Child helper object accessors + + /** + * Returns the view helper of this TimeAxis + * + * @return the view helper of this TimeAxis + */ + ImageFrameTimeAxisView* get_view() ; + + + //---------------------------------------------------------------------------------// + // Emitted Signals + + /** Emitted when a Marker Time Axis is Added, or associated with, this time axis */ + SigC::Signal2 MarkerTimeAxisAdded ; + + /** Emitted when a Marker Time Axis is removed, from this time axis */ + SigC::Signal2 MarkerTimeAxisRemoved ; + + protected: + + private: + /** + * convenience method to select a new track color and apply it to the view and view items + * + */ + void select_track_color() ; + + /** + * Handles the building of the popup menu + */ + virtual void build_display_menu() ; + + /** + * handles the building of the ImageFrameView sub menu + */ + void create_imageframe_menu() ; + + /* We may have multiple marker views, but each marker view should only be associated with one timeaxisview */ + typedef std::list MarkerTimeAxisList ; + MarkerTimeAxisList marker_time_axis_list; + + /* the TimeAxis view helper */ + ImageFrameTimeAxisView *view ; + + // popup menu widgets + Gtk::Menu *image_action_menu ; + Gtk::Menu *imageframe_menu ; + Gtk::Menu *imageframe_item_menu ; + +}; /* class ImageFrameTimeAxis */ + +#endif /* __ardour_imageframe_time_axis_h__ */ + diff --git a/gtk2_ardour/imageframe_time_axis_group.cc b/gtk2_ardour/imageframe_time_axis_group.cc new file mode 100644 index 0000000000..228ce8bb2c --- /dev/null +++ b/gtk2_ardour/imageframe_time_axis_group.cc @@ -0,0 +1,461 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include +#include + +#include "imageframe_time_axis_group.h" +#include "imageframe_time_axis_view.h" +#include "imageframe_view.h" +#include "imageframe_time_axis.h" +#include "canvas-simplerect.h" +#include "region_selection.h" +#include "public_editor.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace ARDOUR ; + +//---------------------------------------------------------------------------------------// +// Constructor / Desctructor + +/** + * Constructs a new ImageFrameTimeAxisGroup. + * + * @param iftav the parent ImageFrameTimeAxis of this view helper + * @param group_id the unique name/id of this group + */ +ImageFrameTimeAxisGroup::ImageFrameTimeAxisGroup(ImageFrameTimeAxisView& iftav, std::string group_id) + : _view_helper(iftav), _group_id(group_id) +{ + selected_imageframe_item = 0 ; + is_selected = false ; +} + +/** + * Destructor + * Responsible for destroying any Items that may have been added to this group + * + */ +ImageFrameTimeAxisGroup::~ImageFrameTimeAxisGroup() +{ + // Destroy all the ImageFramViews that we have + for(ImageFrameViewList::iterator iter = imageframe_views.begin(); iter != imageframe_views.end(); ++iter) + { + ImageFrameView* ifv = *iter ; + + ImageFrameViewList::iterator next = iter ; + next++ ; + + imageframe_views.erase(iter) ; + + delete ifv ; + ifv = 0 ; + + iter = next ; + } + + GoingAway() ; /* EMIT_SIGNAL */ +} + + +//---------------------------------------------------------------------------------------// +// Name/Id Accessors/Mutators + +/** + * Set the name/Id of this group. + * + * @param new_name the new name of this group + * @param src the identity of the object that initiated the change + */ +void +ImageFrameTimeAxisGroup::set_group_name(std::string new_name, void* src) +{ + if(_group_id != new_name) + { + std::string temp_name = _group_id ; + _group_id = new_name ; + NameChanged(_group_id, temp_name, src) ; /* EMIT_SIGNAL */ + } +} + +/** + * Returns the id of this group + * The group id must be unique upon a time axis + * + * @return the id of this group + */ +std::string +ImageFrameTimeAxisGroup::get_group_name() const +{ + return(_group_id) ; +} + + +//---------------------------------------------------------------------------------------// +// ui methods & data + +/** + * Sets the height of the time axis view and the item upon it + * + * @param height the new height + */ +int +ImageFrameTimeAxisGroup::set_item_heights(gdouble h) +{ + /* limit the values to something sane-ish */ + if (h < 10.0 || h > 1000.0) + { + return(-1) ; + } + + // set the heights of all the imaeg frame views within the group + for(ImageFrameViewList::const_iterator citer = imageframe_views.begin(); citer != imageframe_views.end(); ++citer) + { + (*citer)->set_height(h) ; + } + + return(0) ; +} + +/** + * Sets the current samples per unit. + * this method tells each item upon the time axis of the change + * + * @param spu the new samples per canvas unit value + */ +int +ImageFrameTimeAxisGroup::set_item_samples_per_units(gdouble spp) +{ + if(spp < 1.0) + { + return(-1) ; + } + + for(ImageFrameViewList::const_iterator citer = imageframe_views.begin(); citer != imageframe_views.end(); ++citer) + { + (*citer)->set_samples_per_unit(spp) ; + } + + return(0) ; +} + +/** + * Sets the color of the items contained uopn this view helper + * + * @param color the new base color + */ +void +ImageFrameTimeAxisGroup::apply_item_color(GdkColor& color) +{ + region_color = color ; + for(ImageFrameViewList::const_iterator citer = imageframe_views.begin(); citer != imageframe_views.end(); citer++) + { + (*citer)->set_color (region_color) ; + } +} + + + +//---------------------------------------------------------------------------------------// +// child ImageFrameView methods + +/** + * Adds an ImageFrameView to the list of items upon this time axis view helper + * the new ImageFrameView is returned + * + * @param item_id the unique id of the new item + * @param image_id the id/name of the image data we are usin + * @param start the position the new item should be placed upon the time line + * @param duration the duration the new item should be placed upon the timeline + * @param rgb_data the rgb data of the image + * @param width the original image width of the rgb_data (not the size to display) + * @param height the irigianl height of the rgb_data + * @param num_channels the number of channles within the rgb_data + * @param src the identity of the object that initiated the change + */ +ImageFrameView* +ImageFrameTimeAxisGroup::add_imageframe_item(std::string frame_id, jack_nframes_t start, jack_nframes_t duration, unsigned char* rgb_data, uint32_t width, uint32_t height, uint32_t num_channels, void* src) +{ + ImageFrameView* ifv = 0 ; + + //check that there is not already an imageframe with that id + if(get_named_imageframe_item(frame_id) == 0) + { + ifv = new ImageFrameView(frame_id, + GTK_CANVAS_GROUP(_view_helper.canvas_item()), + &(_view_helper.trackview()), + this, + _view_helper.trackview().editor.get_current_zoom(), + region_color, + start, + duration, + rgb_data, + width, + height, + num_channels) ; + + imageframe_views.push_front(ifv) ; + + ifv->GoingAway.connect(bind(slot (*this,&ImageFrameTimeAxisGroup::remove_imageframe_item), (void*)this)) ; + + ImageFrameAdded(ifv, src) ; /* EMIT_SIGNAL */ + } + + return(ifv) ; +} + + +/** + * Returns the named ImageFrameView or 0 if the named view does not exist on this view helper + * + * @param item_id the unique id of the item to search for + * @return the named ImageFrameView, or 0 if it is not held upon this view + */ +ImageFrameView* +ImageFrameTimeAxisGroup::get_named_imageframe_item(std::string frame_id) +{ + ImageFrameView* ifv = 0 ; + + for (ImageFrameViewList::const_iterator i = imageframe_views.begin(); i != imageframe_views.end(); ++i) + { + if (((ImageFrameView*)*i)->get_item_name() == frame_id) + { + ifv = ((ImageFrameView*)*i) ; + break ; + } + } + return(ifv) ; +} + +/** + * Removes the currently selected ImageFrameView + * + * @param src the identity of the object that initiated the change + * @todo need to remoev this, the selected item within group is no longer + * used in favour of a time axis selected item + * @see add_imageframe_view + */ +void +ImageFrameTimeAxisGroup::remove_selected_imageframe_item(void* src) +{ + std::string frame_id ; + + if(selected_imageframe_item) + { + ImageFrameViewList::iterator i ; + + if((i = find(imageframe_views.begin(), imageframe_views.end(), selected_imageframe_item)) != imageframe_views.end()) + { + imageframe_views.erase(i) ; + frame_id = selected_imageframe_item->get_item_name() ; + + // note that we delete the item here + delete(selected_imageframe_item) ; + selected_imageframe_item = 0 ; + + std::string track_id = _view_helper.trackview().name() ; + ImageFrameRemoved(track_id, _group_id, frame_id, src) ; /* EMIT_SIGNAL */ + } + } + else + { + //cerr << "No Selected ImageFrame" << endl ; + } +} + + +/** + * Removes and returns the named ImageFrameView from the list of ImageFrameViews held by this view helper + * + * @param item_id the ImageFrameView unique id to remove + * @param src the identity of the object that initiated the change + * @see add_imageframe_view + */ +ImageFrameView* +ImageFrameTimeAxisGroup::remove_named_imageframe_item(std::string frame_id, void* src) +{ + ImageFrameView* removed = 0 ; + + for(ImageFrameViewList::iterator iter = imageframe_views.begin(); iter != imageframe_views.end(); ++iter) + { + ImageFrameView* tempItem = *iter ; + if(tempItem->get_item_name() == frame_id) + { + removed = tempItem ; + imageframe_views.erase(iter) ; + + if (removed == selected_imageframe_item) + { + selected_imageframe_item = 0 ; + } + + std::string track_id = _view_helper.trackview().name() ; + ImageFrameRemoved(track_id, _group_id, frame_id, src) ; /* EMIT_SIGNAL */ + + // break from the for loop + break ; + } + iter++ ; + } + + return(removed) ; +} + +/** + * Removes ifv from the list of ImageFrameViews upon this TimeAxis. + * if ifv is not upon this TimeAxis, this method takes no action + * + * @param ifv the ImageFrameView to remove + */ +void +ImageFrameTimeAxisGroup::remove_imageframe_item(ImageFrameView* ifv, void* src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameTimeAxisGroup::remove_imageframe_item), ifv, src)); + + ImageFrameViewList::iterator i; + if((i = find (imageframe_views.begin(), imageframe_views.end(), ifv)) != imageframe_views.end()) + { + imageframe_views.erase(i) ; + + std::string frame_id = ifv->get_item_name() ; + std::string track_id = _view_helper.trackview().name() ; + ImageFrameRemoved(track_id, _group_id, frame_id, src) ; /* EMIT_SIGNAL */ + } +} + +//---------------------------------------------------------------------------------------// +// Selected group methods + +/** + * Sets the currently selected item upon this time axis + * + * @param ifv the item to set selected + */ +//void +//ImageFrameTimeAxisGroup::set_selected_imageframe_item(ImageFrameView* ifv) +//{ +// if(selected_imageframe_item) +// { +// selected_imageframe_item->set_selected(false, this) ; +// } +// +// selected_imageframe_item = ifv ; +// +// if(!ifv->get_selected()) +// { +// selected_imageframe_item->set_selected(true, this) ; +// } +//} + + +/** + * Sets the currently selected item upon this time axis to the named item + * + * @param item_id the name/id of the item to set selected + */ +//void +//ImageFrameTimeAxisGroup::set_selected_imageframe_item(std::string frame_id) +//{ +// selected_imageframe_item = get_named_imageframe_item(frame_id) ; +//} + + +/** + * Returns the currently selected item upon this time axis + * + * @return the currently selected item pon this time axis + */ +// ImageFrameView* +// ImageFrameTimeAxisGroup::get_selected_imageframe_item() +// { + // return(selected_imageframe_item) ; +// } + + + +/** + * Returns whether this grou pis currently selected + * + * @returns true if this group is currently selected + */ +bool +ImageFrameTimeAxisGroup::get_selected() const +{ + return(is_selected) ; +} + + +/** + * Sets he selected state of this group + * + * @param yn set true if this group is selected, false otherwise + */ +void +ImageFrameTimeAxisGroup::set_selected(bool yn) +{ + is_selected = yn ; +} + + + +//---------------------------------------------------------------------------------------// +// Handle time axis removal + +/** + * Handles the Removal of this VisualTimeAxis + * This _needs_ to be called to alert others of the removal properly, ie where the source + * of the removal came from. + * + * XXX Although im not too happy about this method of doing things, I cant think of a cleaner method + * just now to capture the source of the removal + * + * @param src the identity of the object that initiated the change + */ +void +ImageFrameTimeAxisGroup::remove_this_group(void* src) +{ + /* + defer to idle loop, otherwise we'll delete this object + while we're still inside this function ... + */ + Gtk::Main::idle.connect(bind(slot(&ImageFrameTimeAxisGroup::idle_remove_this_group), this, src)); +} + +/** + * Callback used to remove this group during the gtk idle loop + * This is used to avoid deleting the obejct while inside the remove_this_group + * method + * + * @param group the ImageFrameTimeAxisGroup to remove + * @param src the identity of the object that initiated the change + */ +gint +ImageFrameTimeAxisGroup::idle_remove_this_group(ImageFrameTimeAxisGroup* group, void* src) +{ + delete group ; + group = 0 ; + group->GroupRemoved(group->get_group_name(), src) ; /* EMIT_SIGNAL */ + return(false) ; +} + diff --git a/gtk2_ardour/imageframe_time_axis_group.h b/gtk2_ardour/imageframe_time_axis_group.h new file mode 100644 index 0000000000..18731acbb8 --- /dev/null +++ b/gtk2_ardour/imageframe_time_axis_group.h @@ -0,0 +1,299 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_imageframe_time_axis_group_h__ +#define __ardour_imageframe_time_axis_group_h__ + +#include +#include + +#include +#include +#include +#include "imageframe_time_axis_view.h" + +class PublicEditor ; +class ImageFrameView ; + +/** + * ImageFrameTimeAxisGroup defines a group/scene of ImageFrame view that can appear upon a time axis + * At the moment this is a bit bare, we really want to add some kind of time constraints upon + * items atht are added to the group, ie bounded by the start and end of the scene, which itself + * needs fleshed out. + * A viewable object may also be useful... + * + */ +class ImageFrameTimeAxisGroup : public SigC::Object +{ + public: + //---------------------------------------------------------------------------------------// + // Constructor / Desctructor + + /** + * Constructs a new ImageFrameTimeAxisGroup. + * + * @param iftav the parent ImageFrameTimeAxis of this view helper + * @param group_id the unique name/id of this group + */ + ImageFrameTimeAxisGroup(ImageFrameTimeAxisView& iftav, std::string group_id) ; + + /** + * Destructor + * Responsible for destroying any Items that may have been added to this group + * + */ + virtual ~ImageFrameTimeAxisGroup() ; + + + //---------------------------------------------------------------------------------------// + // Name/Id Accessors/Mutators + + /** + * Set the name/Id of this group. + * + * @param new_name the new name of this group + * @param src the identity of the object that initiated the change + */ + void set_group_name(std::string new_name, void* src) ; + + /** + * Returns the id of this group + * The group id must be unique upon a time axis + * + * @return the id of this group + */ + std::string get_group_name() const ; + + + //---------------------------------------------------------------------------------------// + // Parent/Child helper object accessors + + /** + * Returns the TimeAxisView thatt his object is acting as a helper for + * + * @return the TimeAxisView that this object is acting as a view helper for + */ + ImageFrameTimeAxisView& get_view() const { return _view_helper ; } + + + + //---------------------------------------------------------------------------------------// + // ui methods & data + + /** + * Sets the height of the time axis view and the item upon it + * + * @param height the new height + */ + int set_item_heights(gdouble) ; + + /** + * Sets the current samples per unit. + * this method tells each item upon the time axis of the change + * + * @param spu the new samples per canvas unit value + */ + int set_item_samples_per_units(gdouble spu) ; + + /** + * Sets the color of the items contained uopn this view helper + * + * @param color the new base color + */ + void apply_item_color(GdkColor&) ; + + + //---------------------------------------------------------------------------------------// + // child ImageFrameView methods + + /** + * Adds an ImageFrameView to the list of items upon this time axis view helper + * the new ImageFrameView is returned + * + * @param item_id the unique id of the new item + * @param image_id the id/name of the image data we are usin + * @param start the position the new item should be placed upon the time line + * @param duration the duration the new item should be placed upon the timeline + * @param rgb_data the rgb data of the image + * @param width the original image width of the rgb_data (not the size to display) + * @param height the irigianl height of the rgb_data + * @param num_channels the number of channles within the rgb_data + * @param src the identity of the object that initiated the change + */ + ImageFrameView* add_imageframe_item(std::string item_id, jack_nframes_t start, jack_nframes_t duration, unsigned char* rgb_data, uint32_t width, uint32_t height, uint32_t num_channels, void* src) ; + + /** + * Returns the named ImageFrameView or 0 if the named view does not exist on this view helper + * + * @param item_id the unique id of the item to search for + * @return the named ImageFrameView, or 0 if it is not held upon this view + */ + ImageFrameView* get_named_imageframe_item(std::string item_id) ; + + /** + * Removes the currently selected ImageFrameView + * + * @param src the identity of the object that initiated the change + * @see add_imageframe_view + */ + void remove_selected_imageframe_item(void* src) ; + + /** + * Removes and returns the named ImageFrameView from the list of ImageFrameViews held by this view helper + * + * @param item_id the ImageFrameView unique id to remove + * @param src the identity of the object that initiated the change + * @see add_imageframe_view + */ + ImageFrameView* remove_named_imageframe_item(std::string item_id, void* src) ; + + /** + * Removes ifv from the list of ImageFrameViews upon this TimeAxis. + * if ifv is not upon this TimeAxis, this method takes no action + * + * @param ifv the ImageFrameView to remove + */ + void remove_imageframe_item(ImageFrameView*, void* src) ; + + + //---------------------------------------------------------------------------------------// + // Selected group methods + + + // removed in favour of a track level selectewd item + // this is simply easier to manage a singularly selected item, rather than + // a selected item within each group + + /** + * Sets the currently selected item upon this time axis + * + * @param ifv the item to set selected + */ + //void set_selected_imageframe_item(ImageFrameView* ifv) ; + + /** + * Sets the currently selected item upon this time axis to the named item + * + * @param item_id the name/id of the item to set selected + */ + //void set_selected_imageframe_item(std::string item_id) ; + + /** + * Returns the currently selected item upon this time axis + * + * @return the currently selected item pon this time axis + */ + //ImageFrameView* get_selected_imageframe_item() ; + + /** + * Returns whether this grou pis currently selected + * + * @returns true if this group is currently selected + */ + bool get_selected() const ; + + /** + * Sets he selected state of this group + * + * @param yn set true if this group is selected, false otherwise + */ + void set_selected(bool yn) ; + + //---------------------------------------------------------------------------------------// + // Handle group removal + + /** + * Handles the Removal of this VisualTimeAxis + * This _needs_ to be called to alert others of the removal properly, ie where the source + * of the removal came from. + * + * XXX Although im not too happy about this method of doing things, I cant think of a cleaner method + * just now to capture the source of the removal + * + * @param src the identity of the object that initiated the change + */ + virtual void remove_this_group(void* src) ; + + //---------------------------------------------------------------------------------// + // Emitted Signals + + SigC::Signal0 GoingAway ; + + /** + * Emitted when this Group has been removed + * This is different to the GoingAway signal in that this signal + * is emitted during the deletion of this Time Axis, and not during + * the destructor, this allows us to capture the source of the deletion + * event + */ + SigC::Signal2 GroupRemoved ; + + /** Emitted when we have changed the name of this TimeAxis */ + SigC::Signal3 NameChanged ; + + /** Emitted when an ImageFrameView is added to this group */ + SigC::Signal2 ImageFrameAdded ; + + /** Emitted when an ImageFrameView is removed from this group */ + SigC::Signal4 ImageFrameRemoved ; + + protected: + + + private: + /** + * convenience method to re-get the samples per unit and tell items upon this view + * + */ + void reset_samples_per_unit() ; + + /** + * Callback used to remove this group during the gtk idle loop + * This is used to avoid deleting the obejct while inside the remove_this_group + * method + * + * @param group the ImageFrameTimeAxisGroup to remove + * @param src the identity of the object that initiated the change + */ + static gint idle_remove_this_group(ImageFrameTimeAxisGroup* group, void* src) ; + + /** The list of ImageFrameViews held by this view helper */ + typedef std::list ImageFrameViewList ; + ImageFrameViewList imageframe_views ; + + /** the currently selected time axis item upon this time axis */ + ImageFrameView* selected_imageframe_item ; + + /** the view helper that this object is acting as a container upon on */ + ImageFrameTimeAxisView& _view_helper ; + + /** the is of this group */ + std::string _group_id ; + + /* XXX why are these different? */ + GdkColor region_color ; + uint32_t stream_base_color ; + + /** indicates if this group is currently selected */ + bool is_selected ; + +} ; /* class ImageFrameTimeAxisGroup */ + +#endif /* __ardour_imageframe_time_axis_group_h__ */ diff --git a/gtk2_ardour/imageframe_time_axis_view.cc b/gtk2_ardour/imageframe_time_axis_view.cc new file mode 100644 index 0000000000..20ccb7d61f --- /dev/null +++ b/gtk2_ardour/imageframe_time_axis_view.cc @@ -0,0 +1,460 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include + +#include + +#include "imageframe_time_axis_view.h" +#include "imageframe_time_axis_group.h" +#include "imageframe_view.h" +#include "imageframe_time_axis.h" +#include "canvas-simplerect.h" +#include "region_selection.h" +#include "public_editor.h" +#include "rgb_macros.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace ARDOUR ; +using namespace Editing; + +//---------------------------------------------------------------------------------------// +// Constructor / Desctructor + +/** + * Constructs a new ImageFrameTimeAxisView. + * + * @param ifta the parent ImageFrameTimeAxis of this view helper + */ +ImageFrameTimeAxisView::ImageFrameTimeAxisView (ImageFrameTimeAxis& tv) + : _trackview (tv) +{ + region_color = _trackview.color() ; + stream_base_color = color_map[cImageTrackBase] ; + + canvas_group = gtk_canvas_item_new (GTK_CANVAS_GROUP(_trackview.canvas_display), gtk_canvas_group_get_type (), 0) ; + + canvas_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_group), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 1000000.0, + "y2", (double) tv.height, + "outline_color_rgba", color_map[cImageTrackOutline], + "fill_color_rgba", stream_base_color, + 0) ; + + gtk_signal_connect(GTK_OBJECT(canvas_rect), "event", (GtkSignalFunc) PublicEditor::canvas_imageframe_view_event, &_trackview) ; + + _samples_per_unit = _trackview.editor.get_current_zoom() ; + + _trackview.editor.ZoomChanged.connect (slot (*this, &ImageFrameTimeAxisView::reset_samples_per_unit)) ; + + selected_imageframe_group = 0 ; + selected_imageframe_view = 0 ; +} + +/** + * Destructor + * Responsible for destroying all items tat may have been added to this time axis + */ +ImageFrameTimeAxisView::~ImageFrameTimeAxisView() +{ + // Destroy all the ImageFrameGroups that we have + + for(ImageFrameGroupList::iterator iter = imageframe_groups.begin(); iter != imageframe_groups.end(); ++iter) + { + ImageFrameTimeAxisGroup* iftag = (*iter) ; + + ImageFrameGroupList::iterator next = iter ; + next++ ; + + // remove the front element + imageframe_groups.erase(iter) ; + + delete iftag ; + iftag = 0 ; + + iter = next ; + } + + // Destroy all our canvas components + if(canvas_rect) + { + gtk_object_destroy(GTK_OBJECT(canvas_rect)) ; + canvas_rect = 0 ; + } + + if(canvas_group) + { + gtk_object_destroy(GTK_OBJECT(canvas_group)); + canvas_group = 0 ; + } +} + + +//---------------------------------------------------------------------------------------// +// ui methods & data + +/** + * Sets the height of the time axis view and the item upon it + * + * @param height the new height + */ +int +ImageFrameTimeAxisView::set_height (gdouble h) +{ + /* limit the values to something sane-ish */ + if (h < 10.0 || h > 1000.0) + { + return(-1) ; + } + + if(canvas_rect != 0) + { + gtk_object_set(GTK_OBJECT(canvas_rect), "y2", h, NULL) ; + } + + for(ImageFrameGroupList::const_iterator citer = imageframe_groups.begin(); citer != imageframe_groups.end(); ++citer) + { + (*citer)->set_item_heights(h) ; + } + + return(0) ; +} + +/** + * Sets the position of this view helper on the canvas + * + * @param x the x position upon the canvas + * @param y the y position npon the canvas + */ +int +ImageFrameTimeAxisView::set_position (gdouble x, gdouble y) + +{ + gtk_canvas_item_set (canvas_group, "x", x, "y", y, NULL); + return 0; +} + +/** + * Sets the current samples per unit. + * this method tells each item upon the time axis of the change + * + * @param spu the new samples per canvas unit value + */ +int +ImageFrameTimeAxisView::set_samples_per_unit (gdouble spp) +{ + if (spp < 1.0) { + return(-1) ; + } + + _samples_per_unit = spp; + + for(ImageFrameGroupList::const_iterator citer = imageframe_groups.begin(); citer != imageframe_groups.end(); ++citer) + { + (*citer)->set_item_samples_per_units(spp) ; + } + + return(0) ; +} + +/** + * Sets the color of the items contained uopn this view helper + * + * @param color the new base color + */ +void +ImageFrameTimeAxisView::apply_color(GdkColor& color) +{ + region_color = color ; + for(ImageFrameGroupList::const_iterator citer = imageframe_groups.begin(); citer != imageframe_groups.end(); citer++) + { + (*citer)->apply_item_color(region_color) ; + } +} + + +/** + * convenience method to re-get the samples per unit and tell items upon this view + * + */ +void +ImageFrameTimeAxisView::reset_samples_per_unit () +{ + set_samples_per_unit (_trackview.editor.get_current_zoom()); +} + + +//---------------------------------------------------------------------------------------// +// Child ImageFrameTimeAxisGroup Accessors/Mutators + +/** + * Adds an ImageFrameTimeAxisGroup to the list of items upon this time axis view helper + * the new ImageFrameTimeAxisGroup is returned + * + * @param group_id the unique id of the new group + * @param src the identity of the object that initiated the change + */ +ImageFrameTimeAxisGroup* +ImageFrameTimeAxisView::add_imageframe_group(std::string group_id, void* src) +{ + ImageFrameTimeAxisGroup* iftag = 0 ; + + //check that there is not already a group with that id + if(get_named_imageframe_group(group_id) != 0) + { + // iftag = 0 ; + } + else + { + iftag = new ImageFrameTimeAxisGroup(*this, group_id) ; + + imageframe_groups.push_front(iftag) ; + + iftag->GoingAway.connect(bind(slot (*this,&ImageFrameTimeAxisView::remove_imageframe_group), iftag, (void*)this)) ; + + ImageFrameGroupAdded(iftag, src) ; /* EMIT_SIGNAL */ + } + + return(iftag) ; +} + +/** + * Returns the named ImageFrameTimeAxisGroup or 0 if the named group does not exist on this view helper + * + * @param group_id the unique id of the group to search for + * @return the named ImageFrameTimeAxisGroup, or 0 if it is not held upon this view + */ +ImageFrameTimeAxisGroup* +ImageFrameTimeAxisView::get_named_imageframe_group(std::string group_id) +{ + ImageFrameTimeAxisGroup* iftag = 0 ; + + for(ImageFrameGroupList::iterator i = imageframe_groups.begin(); i != imageframe_groups.end(); ++i) + { + if (((ImageFrameTimeAxisGroup*)*i)->get_group_name() == group_id) + { + iftag = ((ImageFrameTimeAxisGroup*)*i) ; + break ; + } + } + + return(iftag) ; +} + + +/** + * Removes and returns the named ImageFrameTimeAxisGroup from the list of ImageFrameTimeAxisGroup held by this view helper + * + * @param group_id the ImageFrameTimeAxisGroup unique id to remove + * @param src the identity of the object that initiated the change + * @see add_imageframe_group + */ +ImageFrameTimeAxisGroup* +ImageFrameTimeAxisView::remove_named_imageframe_group(std::string group_id, void* src) +{ + ImageFrameTimeAxisGroup* removed = 0 ; + + for(ImageFrameGroupList::iterator iter = imageframe_groups.begin(); iter != imageframe_groups.end(); ++iter) + { + if(((ImageFrameTimeAxisGroup*)*iter)->get_group_name() == group_id) + { + removed = (*iter) ; + imageframe_groups.erase(iter) ; + + if(removed == selected_imageframe_group) + { + selected_imageframe_group = 0 ; + } + + ImageFrameGroupRemoved(removed->get_group_name(), src) ; /* EMIT_SIGNAL */ + + // break from the for loop + break ; + } + iter++ ; + } + + return(removed) ; +} + + +/** + * Removes the specified ImageFrameTimeAxisGroup from the list of ImageFrameTimeAxisGroups upon this TimeAxis. + * + * @param iftag the ImageFrameView to remove + */ +void +ImageFrameTimeAxisView::remove_imageframe_group(ImageFrameTimeAxisGroup* iftag, void* src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameTimeAxisView::remove_imageframe_group), iftag, src)); + + ImageFrameGroupList::iterator i; + if((i = find (imageframe_groups.begin(), imageframe_groups.end(), iftag)) != imageframe_groups.end()) + { + imageframe_groups.erase(i) ; + + ImageFrameGroupRemoved(iftag->get_group_name(), src) ; /* EMIT_SIGNAL */ + } +} + + + + +//---------------------------------------------------------------------------------------// +// Selected group methods + +/** + * Sets the currently selected group upon this time axis + * + * @param ifv the item to set selected + */ +void +ImageFrameTimeAxisView::set_selected_imageframe_group(ImageFrameTimeAxisGroup* iftag) +{ + if(selected_imageframe_group) + { + selected_imageframe_group->set_selected(false) ; + } + + selected_imageframe_group = iftag ; + selected_imageframe_group->set_selected(true) ; +} + +/** + * Clears the currently selected image frame group unpo this time axis + * +*/ +void +ImageFrameTimeAxisView::clear_selected_imageframe_group() +{ + if(selected_imageframe_group) + { + selected_imageframe_group->set_selected(false) ; + } + selected_imageframe_group = 0 ; +} + +/** + * Returns the currently selected group upon this time axis + * + * @return the currently selected group upon this time axis + */ +ImageFrameTimeAxisGroup* +ImageFrameTimeAxisView::get_selected_imageframe_group() const +{ + return(selected_imageframe_group) ; +} + +//---------------------------------------------------------------------------------------// +// Selected item methods + +/** + * Sets the currently selected imag frame view item + * + * @param iftag the group the selected item is part + * @param ifv the selected item + */ +void +ImageFrameTimeAxisView::set_selected_imageframe_view(ImageFrameTimeAxisGroup* iftag, ImageFrameView* ifv) +{ + set_selected_imageframe_group(iftag) ; + + if(selected_imageframe_view) + { + selected_imageframe_view->set_selected(false, this) ; + } + + selected_imageframe_view = ifv ; + selected_imageframe_view->set_selected(true, this) ; +} + +/** + * Clears the currently selected image frame view item + * + */ +void +ImageFrameTimeAxisView::clear_selected_imageframe_item(bool clear_group) +{ + if(clear_group) + { + clear_selected_imageframe_group() ; + } + + if(selected_imageframe_view) + { + selected_imageframe_view->set_selected(false, this) ; + } + selected_imageframe_view = 0 ; +} + +/** + * Returns the currently selected image frame view item upon this time axis + * + * @return the currently selected image frame view item + */ +ImageFrameView* +ImageFrameTimeAxisView::get_selected_imageframe_view() const +{ + return(selected_imageframe_view) ; +} + + + + +void +ImageFrameTimeAxisView::set_imageframe_duration_sec(double sec) +{ + if(selected_imageframe_group && selected_imageframe_view) + { + selected_imageframe_view->set_duration((jack_nframes_t) (sec * _trackview.editor.current_session()->frame_rate()), this) ; + } +} + + + +/** + * Removes the currently selected ImageFrame view item + * + * @param src the identity of the object that initiated the change + * @see add_imageframe_group + */ +void +ImageFrameTimeAxisView::remove_selected_imageframe_item(void* src) +{ + if(selected_imageframe_group && selected_imageframe_view) + { + ImageFrameView* temp_item = selected_imageframe_view ; + selected_imageframe_group->remove_imageframe_item(temp_item, src) ; + + // XXX although we have removed the item from the group, we need the group id still set within the + // item as the remove method requires this data when telling others about the deletion + // to fully specify the item we need the track, group and item id + selected_imageframe_view->remove_this_item(src) ; + clear_selected_imageframe_item(false) ; + } +} + diff --git a/gtk2_ardour/imageframe_time_axis_view.h b/gtk2_ardour/imageframe_time_axis_view.h new file mode 100644 index 0000000000..41c111fdc2 --- /dev/null +++ b/gtk2_ardour/imageframe_time_axis_view.h @@ -0,0 +1,271 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_imageframe_time_axis_view_h__ +#define __ardour_imageframe_time_axis_view_h__ + +#include +#include + +#include +#include +#include + +class PublicEditor ; +class ImageFrameTimeAxis ; +class ImageFrameView ; +class ImageFrameTimeAxisGroup ; + +/** + * ImageFrameTimeAxisView defines the time axis view helper + * This object is responsible for the time axis canvas view, and + * maintains the list of items that have been added to it + * + */ +class ImageFrameTimeAxisView : public SigC::Object +{ + public: + //---------------------------------------------------------------------------------------// + // Constructor / Desctructor + + /** + * Constructs a new ImageFrameTimeAxisView. + * + * @param ifta the parent ImageFrameTimeAxis of this view helper + */ + ImageFrameTimeAxisView(ImageFrameTimeAxis& ifta) ; + + /** + * Destructor + * Responsible for destroying all items tat may have been added to this time axis + */ + ~ImageFrameTimeAxisView () ; + + //---------------------------------------------------------------------------------------// + // Parent/Child helper object accessors + + /** + * Returns the TimeAxisView thatt his object is acting as a helper for + * + * @return the TimeAxisView that this object is acting as a view helper for + */ + ImageFrameTimeAxis& trackview() { return _trackview; } + + /** + * + */ + GtkCanvasItem* canvas_item() { return canvas_group; } + + + //---------------------------------------------------------------------------------------// + // ui methods & data + + /** + * Sets the height of the time axis view and the item upon it + * + * @param height the new height + */ + int set_height(gdouble) ; + + /** + * Sets the position of this view helper on the canvas + * + * @param x the x position upon the canvas + * @param y the y position upon the canvas + */ + int set_position(gdouble x, gdouble y) ; + + /** + * Sets the current samples per unit. + * this method tells each item upon the time axis of the change + * + * @param spu the new samples per canvas unit value + */ + int set_samples_per_unit(gdouble spu) ; + + /** + * Returns the current samples per unit of this time axis view helper + * + * @return the current samples per unit of this time axis view helper + */ + gdouble get_samples_per_unit() { return _samples_per_unit; } + + /** + * Sets the color of the items contained uopn this view helper + * + * @param color the new base color + */ + void apply_color (GdkColor&) ; + + //---------------------------------------------------------------------------------------// + // Child ImageFrameTimeAxisGroup Accessors/Mutators + + /** + * Adds an ImageFrameTimeAxisGroup to the list of items upon this time axis view helper + * the new ImageFrameTimeAxisGroup is returned + * + * @param group_id the unique id of the new group + * @param src the identity of the object that initiated the change + */ + ImageFrameTimeAxisGroup* add_imageframe_group(std::string group_id, void* src) ; + + /** + * Returns the named ImageFrameTimeAxisGroup or 0 if the named group does not exist on this view helper + * + * @param group_id the unique id of the group to search for + * @return the named ImageFrameTimeAxisGroup, or 0 if it is not held upon this view + */ + ImageFrameTimeAxisGroup* get_named_imageframe_group(std::string group_id) ; + + /** + * Removes and returns the named ImageFrameTimeAxisGroup from the list of ImageFrameTimeAxisGroup held by this view helper + * + * @param group_id the ImageFrameTimeAxisGroup unique id to remove + * @param src the identity of the object that initiated the change + * @see add_imageframe_group + */ + ImageFrameTimeAxisGroup* remove_named_imageframe_group(std::string group_id, void* src) ; + + /** + * Removes the specified ImageFrameTimeAxisGroup from the list of ImageFrameTimeAxisGroups upon this TimeAxis. + * + * @param iftag the ImageFrameView to remove + */ + void remove_imageframe_group(ImageFrameTimeAxisGroup* iftag, void* src) ; + + + //---------------------------------------------------------------------------------------// + // Selected group methods + + /** + * Sets the currently selected group upon this time axis + * + * @param ifv the item to set selected + */ + void set_selected_imageframe_group(ImageFrameTimeAxisGroup* iftag) ; + + /** + * Clears the currently selected image frame group unpo this time axis + * + */ + void clear_selected_imageframe_group() ; + + /** + * Returns the currently selected group upon this time axis + * + * @return the currently selected group upon this time axis + */ + ImageFrameTimeAxisGroup* get_selected_imageframe_group() const ; + + + /** + * Sets the duration of the selected ImageFrameView to the specified number of seconds + * + * @param sec the duration to set the ImageFrameView to, in seconds + */ + void set_imageframe_duration_sec(double sec) ; + + //---------------------------------------------------------------------------------------// + // Selected item methods + + /** + * Sets the currently selected image frame view item + * + * @param iftag the group the selected item is part + * @param ifv the selected item + */ + void set_selected_imageframe_view(ImageFrameTimeAxisGroup* iftag, ImageFrameView* ifv) ; + + /** + * Clears the currently selected image frame view item + * + * @param clear_group set true if the selected parent group of the item should be cleared also + */ + void clear_selected_imageframe_item(bool clear_group) ; + + /** + * Returns the currently selected image frame view item upon this time axis + * + * @return the currently selected image frame view item + */ + ImageFrameView* get_selected_imageframe_view() const ; + + + + /** + * Removes the currently selected ImageFrameTimeAxisGroup + * + * @param src the identity of the object that initiated the change + * @see add_imageframe_group + */ + void remove_selected_imageframe_item(void* src) ; + + + //---------------------------------------------------------------------------------// + // Emitted Signals + + /** Emitted when and ImageFrameGroup is added to this time axis */ + SigC::Signal2 ImageFrameGroupAdded ; + + /** Emitted when an ImageFrameGroup is removed from this time axis */ + SigC::Signal2 ImageFrameGroupRemoved ; + + protected: + + + private: + /** + * convenience method to re-get the samples per unit and tell items upon this view + * + */ + void reset_samples_per_unit() ; + + /** + * The list of ImageFrameViews held by this view helper */ + typedef std::list ImageFrameGroupList ; + ImageFrameGroupList imageframe_groups ; + + /** the currently selected time axis item upon this time axis */ + ImageFrameTimeAxisGroup* selected_imageframe_group ; + + /** + * thecurrently selected image frame view + * we keep this here so that we only have one per view, not one per group + */ + ImageFrameView* selected_imageframe_view ; + + + + /* the TimeAxisView that this object is acting as the view helper for */ + ImageFrameTimeAxis& _trackview ; + + GtkCanvasItem *canvas_group ; + GtkCanvasItem *canvas_rect; /* frame around the whole thing */ + + /** the current samples per unit */ + double _samples_per_unit ; + + /* XXX why are these different? */ + GdkColor region_color ; + uint32_t stream_base_color ; + +} ; /* class ImageFrameTimeAxisView */ + +#endif /* __ardour_imageframe_time_axis_view_h__ */ diff --git a/gtk2_ardour/imageframe_view.cc b/gtk2_ardour/imageframe_view.cc new file mode 100644 index 0000000000..27fe741204 --- /dev/null +++ b/gtk2_ardour/imageframe_view.cc @@ -0,0 +1,395 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include +#include + +#include "imageframe_time_axis.h" +#include "imageframe_time_axis_group.h" +#include "marker_time_axis.h" +#include "marker_time_axis_view.h" +#include "canvas-simplerect.h" +#include "public_editor.h" +#include "utils.h" +#include "imageframe_view.h" +#include "canvas-imageframe.h" +#include "gui_thread.h" + +using namespace SigC ; +using namespace ARDOUR ; + +SigC::Signal1 ImageFrameView::GoingAway; + +/** + * Constructs a new ImageFrameView upon the canvas + * + * @param item_id unique id of this item + * @param parent the parent canvas item + * @param tv the time axis view that this item is to be placed upon + * @param group the ImageFrameGroup that this item is a member of + * @param spu the current samples per canvas unit + * @param start the start frame ogf this item + * @param duration the duration of this item + * @param rgb_data the rgb data of the image + * @param width the width of the original rgb_data image data + * @param height the width of the origianl rgb_data image data + * @param num_channels the number of color channels within rgb_data + */ +ImageFrameView::ImageFrameView(std::string item_id, + GtkCanvasGroup *parent, + ImageFrameTimeAxis* tv, + ImageFrameTimeAxisGroup* item_group, + double spu, + GdkColor& basic_color, + jack_nframes_t start, + jack_nframes_t duration, + unsigned char* rgb_data, + uint32_t width, + uint32_t height, + uint32_t num_channels) + : TimeAxisViewItem(item_id, parent, *tv, spu, basic_color, start, duration, + TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText| + TimeAxisViewItem::ShowNameHighlight| + TimeAxisViewItem::ShowFrame| + TimeAxisViewItem::ShowHandles)) + +{ + the_parent_group = item_group ; + set_name_text(item_id) ; + + image_data_width = width ; + image_data_height = height ; + image_data_num_channels = num_channels ; + + //This should be art_free'd once the ArtPixBuf is destroyed - this should happen when we destroy the imageframe canvas item + unsigned char* the_rgb_data = (unsigned char*) art_alloc(width*height*num_channels) ; + memcpy(the_rgb_data, rgb_data, (width*height*num_channels)) ; + + ArtPixBuf* pbuf ; + pbuf = art_pixbuf_new_rgba(the_rgb_data, width, height, (num_channels * width)); + imageframe = 0 ; + + //calculate our image width based on the track height + double im_ratio = (double)width/(double)height ; + int im_width = (int)((double)(trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE) * im_ratio) ; + + imageframe = gtk_canvas_item_new(GTK_CANVAS_GROUP(group), + gtk_canvas_imageframe_get_type(), + "pixbuf", pbuf, + "x", (gdouble) 1.0, + "y", (gdouble) 1.0, + "anchor", GTK_ANCHOR_NW, + "width", (gdouble) im_width, + "height", (gdouble) (trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE), + NULL) ; + + + gtk_signal_connect (GTK_OBJECT(frame_handle_start), "event", + (GtkSignalFunc) PublicEditor::canvas_imageframe_start_handle_event, + this); + + gtk_signal_connect (GTK_OBJECT(frame_handle_end), "event", + (GtkSignalFunc) PublicEditor::canvas_imageframe_end_handle_event, + this); + + gtk_signal_connect (GTK_OBJECT(group), "event", + (GtkSignalFunc) PublicEditor::canvas_imageframe_item_view_event, this); + + /* handle any specific details required by the initial start end duration values */ + + gtk_canvas_item_raise_to_top(frame_handle_start) ; + gtk_canvas_item_raise_to_top(frame_handle_end) ; + + set_position(start, this) ; + set_duration(duration, this) ; +} + +/** + * Destructor + * Reposible for removing and destroying all marker items associated with this item + */ +ImageFrameView::~ImageFrameView() +{ + GoingAway (this); + + // destroy any marker items we have associated with this item + + for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter) + { + MarkerView* mv = (*iter) ; + + MarkerViewList::iterator next = iter ; + next++ ; + + // remove the item from our marker list + // the current iterator becomes invalid after this point, so we cannot call next upon it + // luckily enough, we already have next + marker_view_list.erase(iter) ; + + // remove the item from the marker time axis + MarkerTimeAxisView* mtav = dynamic_cast(&mv->get_time_axis_view())->get_view() ; + if(mtav) + { + mtav->remove_marker_view(mv, this) ; + } + + mv->set_marked_item(0) ; + delete mv ; + mv = 0 ; + + // set our iterator to next, as we have invalided the current iterator with the call to erase + iter = next ; + } + + // if we are the currently selected item withi the parent track, we need to se-select + if(the_parent_group) + { + if(the_parent_group->get_view().get_selected_imageframe_view() == this) + { + the_parent_group->get_view().clear_selected_imageframe_item(false) ; + } + } + + if(imageframe) + { + gtk_object_destroy(GTK_OBJECT(imageframe)) ; + imageframe = 0 ; + } +} + + +//---------------------------------------------------------------------------------------// +// Position and duration Accessors/Mutators + +/** + * Set the position of this item to the specified value + * + * @param pos the new position + * @param src the identity of the object that initiated the change + * @return true if the position change was a success, false otherwise + */ +bool +ImageFrameView::set_position(jack_nframes_t pos, void* src) +{ + jack_nframes_t old_pos = frame_position ; + + // do the standard stuff + bool ret = TimeAxisViewItem::set_position(pos, src) ; + + // everything went ok with the standard stuff? + if(ret) + { + /* move each of our associated markers with this ImageFrameView */ + for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i) + { + // calculate the offset of the marker + MarkerView* mv = (MarkerView*)*i ; + jack_nframes_t marker_old_pos = mv->get_position() ; + + mv->set_position(pos + (marker_old_pos - old_pos), src) ; + } + } + + return(ret) ; +} + +/** + * Sets the duration of this item + * + * @param dur the new duration of this item + * @param src the identity of the object that initiated the change + * @return true if the duration change was succesful, false otherwise + */ +bool +ImageFrameView::set_duration(jack_nframes_t dur, void* src) +{ + /* do the standard stuff */ + bool ret = TimeAxisViewItem::set_duration(dur, src) ; + + // eveything went ok with the standard stuff? + if(ret) + { + /* handle setting the sizes of our canvas itesm based on the new duration */ + gtk_canvas_item_set(imageframe, "drawwidth", (gdouble) trackview.editor.frame_to_pixel(get_duration()), NULL) ; + } + + return(ret) ; +} + +//---------------------------------------------------------------------------------------// +// Parent Component Methods + +/** + * Sets the parent ImageFrameTimeAxisGroup of thie item + * each Item must be part of exactly one group (or 'scene') upon the timeline + * + * @param group the new parent group + */ +void +ImageFrameView::set_time_axis_group(ImageFrameTimeAxisGroup* group) +{ + the_parent_group = group ; +} + +/** + * Returns the parent group of this item + * + * @return the parent group of this item + */ +ImageFrameTimeAxisGroup* +ImageFrameView::get_time_axis_group() +{ + return(the_parent_group) ; +} + + +//---------------------------------------------------------------------------------------// +// ui methods + +/** + * Set the height of this item + * + * @param h the new height + */ +void +ImageFrameView::set_height (gdouble h) +{ + // set the image size + // @todo might have to re-get the image data, for a large height...hmmm. + double im_ratio = (double)image_data_width/(double)image_data_height ; + int im_width = (int)((double)(h - TimeAxisViewItem::NAME_Y_OFFSET) * im_ratio) ; + gtk_canvas_item_set(imageframe, "width", (gdouble)im_width, NULL) ; + gtk_canvas_item_set(imageframe, "height",(gdouble) (h - TimeAxisViewItem::NAME_Y_OFFSET), NULL) ; + + + gtk_canvas_item_raise_to_top(frame) ; + gtk_canvas_item_raise_to_top(imageframe) ; + gtk_canvas_item_raise_to_top(name_highlight) ; + gtk_canvas_item_raise_to_top(name_text) ; + gtk_canvas_item_raise_to_top(frame_handle_start) ; + gtk_canvas_item_raise_to_top(frame_handle_end) ; + + gtk_canvas_item_set (name_text, "y", h - TimeAxisViewItem::NAME_Y_OFFSET, NULL); + gtk_canvas_item_set (frame, "y2", h, NULL); + + gtk_canvas_item_set (name_highlight, "y1", (gdouble) h - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE, "y2", (gdouble) h - 1.0, NULL); +} + + +//---------------------------------------------------------------------------------------// +// MarkerView methods + +/** + * Adds a markerView to the list of marker views associated with this item + * + * @param item the marker item to add + * @param src the identity of the object that initiated the change + */ +void +ImageFrameView::add_marker_view_item(MarkerView* item, void* src) +{ + marker_view_list.push_back(item) ; + + item->GoingAway.connect(bind(slot(*this, &ImageFrameView::remove_marker_view_item), (void*)this)); + + MarkerViewAdded(item, src) ; /* EMIT_SIGNAL */ +} + +/** + * Removes the named marker view from the list of marker view associated with this item + * The Marker view is not destroyed on removal, so the caller must handle the item themself + * + * @param markId the id/name of the item to remove + * @param src the identity of the object that initiated the change + * @return the removed marker item + */ +MarkerView* +ImageFrameView::remove_named_marker_view_item(std::string markerId, void* src) +{ + MarkerView* mv = 0 ; + MarkerViewList::iterator i = marker_view_list.begin() ; + + while(i != marker_view_list.end()) + { + if (((MarkerView*)*i)->get_item_name() == markerId) + { + mv = (*i) ; + + marker_view_list.erase(i) ; + + MarkerViewRemoved(mv,src) ; /* EMIT_SIGNAL */ + + // iterator is now invalid, but since we should only ever have + // one item with the specified name, things are ok, and we can + // break from the while loop + break ; + } + i++ ; + } + + return(mv) ; +} + +/** + * Removes item from the list of marker views assocaited with this item + * This method will do nothing if item if not assiciated with this item + * + * @param item the item to remove + * @param src the identity of the object that initiated the change + */ +void +ImageFrameView::remove_marker_view_item(MarkerView* mv, void* src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &ImageFrameView::remove_marker_view_item), mv, src)); + + MarkerViewList::iterator i ; + + if((i = find (marker_view_list.begin(), marker_view_list.end(), mv)) != marker_view_list.end()) { + marker_view_list.erase(i) ; + MarkerViewRemoved (mv, src) ; /* EMIT_SIGNAL */ + } +} + +/** + * Determines if the named marker is one of those associated with this item + * + * @param markId the id/name of the item to search for + */ +bool +ImageFrameView::has_marker_view_item(std::string mname) +{ + bool result = false ; + + for (MarkerViewList::iterator ci = marker_view_list.begin(); ci != marker_view_list.end(); ++ci) + { + if (((MarkerView*)*ci)->get_item_name() == mname) + { + result = true ; + + // found the item, so we can break the for loop + break ; + } + } + + return(result) ; +} diff --git a/gtk2_ardour/imageframe_view.h b/gtk2_ardour/imageframe_view.h new file mode 100644 index 0000000000..6a6aa3d33a --- /dev/null +++ b/gtk2_ardour/imageframe_view.h @@ -0,0 +1,212 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __gtk_ardour_imageframe_view_h__ +#define __gtk_ardour_imageframe_view_h__ + +#include +#include +#include +#include +#include + +#include "enums.h" +#include "time_axis_view_item.h" +#include "marker_view.h" + +class ImageFrameTimeAxis; +class ImageFrameTimeAxisGroup ; + +/** + * An ImageFrameItem to display an image upon the ardour time line + * + */ +class ImageFrameView : public TimeAxisViewItem +{ + public: + //---------------------------------------------------------------------------------------// + // Constructor / Desctructor + + /** + * Constructs a new ImageFrameView upon the canvas + * + * @param item_id unique id of this item + * @param parent the parent canvas item + * @param tv the time axis view that this item is to be placed upon + * @param group the ImageFrameGroup that this item is a member of + * @param spu the current samples per canvas unit + * @param start the start frame ogf this item + * @param duration the duration of this item + * @param rgb_data the rgb data of the image + * @param width the width of the original rgb_data image data + * @param height the width of the origianl rgb_data image data + * @param num_channels the number of color channels within rgb_data + */ + ImageFrameView(std::string item_id, + GtkCanvasGroup *parent, + ImageFrameTimeAxis *tv, + ImageFrameTimeAxisGroup* group, + double spu, + GdkColor& base_color, + jack_nframes_t start, + jack_nframes_t duration, + unsigned char* rgb_data, + uint32_t width, + uint32_t height, + uint32_t num_channels) ; + + /** + * Destructor + * Reposible for removing and destroying all marker items associated with this item + */ + ~ImageFrameView() ; + + static SigC::Signal1 GoingAway; + + //---------------------------------------------------------------------------------------// + // Position and duration Accessors/Mutators + + /** + * Set the position of this item to the specified value + * + * @param pos the new position + * @param src the identity of the object that initiated the change + * @return true if the position change was a success, false otherwise + */ + virtual bool set_position(jack_nframes_t pos, void* src) ; + + /** + * Sets the duration of this item + * + * @param dur the new duration of this item + * @param src the identity of the object that initiated the change + * @return true if the duration change was succesful, false otherwise + */ + virtual bool set_duration(jack_nframes_t dur, void* src) ; + + //---------------------------------------------------------------------------------------// + // Parent Component Methods + + /** + * Sets the parent ImageFrameTimeAxisGroup of thie item + * each Item must be part of exactly one group (or 'scene') upon the timeline + * + * @param group the new parent group + */ + void set_time_axis_group(ImageFrameTimeAxisGroup* group) ; + + /** + * Returns the parent group of this item + * + * @return the parent group of this item + */ + ImageFrameTimeAxisGroup* get_time_axis_group() ; + + //---------------------------------------------------------------------------------------// + // ui methods + + /** + * Set the height of this item + * + * @param h the new height + */ + virtual void set_height(gdouble h) ; + + + //---------------------------------------------------------------------------------------// + // MarkerView methods + + /** + * Adds a markerView to the list of marker views associated with this item + * + * @param item the marker item to add + * @param src the identity of the object that initiated the change + */ + void add_marker_view_item(MarkerView* item, void* src) ; + + /** + * Removes the named marker view from the list of marker view associated with this item + * The Marker view is not destroyed on removal, so the caller must handle the item themself + * + * @param markId the id/name of the item to remove + * @param src the identity of the object that initiated the change + * @return the removed marker item + */ + MarkerView* remove_named_marker_view_item(std::string markId, void* src) ; + + /** + * Removes item from the list of marker views assocaited with this item + * This method will do nothing if item if not assiciated with this item + * The Marker view is not destroyed on removal, so the caller must handle the item themself + * + * @param item the item to remove + * @param src the identity of the object that initiated the change + */ + void remove_marker_view_item(MarkerView* item, void* src) ; + + /** + * Determines if the named marker is one of those associated with this item + * + * @param markId the id/name of the item to search for + */ + bool has_marker_view_item(std::string markId) ; + + + //---------------------------------------------------------------------------------// + // Emitted Signals + + /** Emitted when a marker Item is added to this Item */ + SigC::Signal2 MarkerViewAdded ; + + /** Emitted when a Marker Item is added to this Item */ + SigC::Signal2 MarkerViewRemoved ; + + private: + /** the list of MarkerViews associated with this item */ + typedef std::list MarkerViewList ; + MarkerViewList marker_view_list ; + + + /** The parent group that this item is a member of */ + ImageFrameTimeAxisGroup* the_parent_group ; + + // ------- Image data ----------- + + /** the image data that we display */ + //unsigned char* the_rgb_data ; + + /** The width of the image contained within the_rgb_data */ + uint32_t image_data_width ; + + /** The height of the image contained within the_rgb_data */ + uint32_t image_data_height ; + + /** the number of channels contained in the_rgb_data */ + uint32_t image_data_num_channels ; + + + // ------- Our canvas element ----------- + + /** the CanvasImageFrame to display the image */ + GtkCanvasItem* imageframe ; + +} ; /* class ImageFrameView */ + +#endif /* __gtk_ardour_imageframe_view_h__ */ diff --git a/gtk2_ardour/io_menu.h b/gtk2_ardour/io_menu.h new file mode 100644 index 0000000000..b1fb785128 --- /dev/null +++ b/gtk2_ardour/io_menu.h @@ -0,0 +1,25 @@ +/* + Copyright (C) 1999-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __gtk_ardour_io_menu_h__ +#define __gtk_ardour_io_menu_h__ + + +#endif /* __gtk_ardour_io_menu_h__ */ diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc new file mode 100644 index 0000000000..0d013c72f4 --- /dev/null +++ b/gtk2_ardour/io_selector.cc @@ -0,0 +1,857 @@ +/* + Copyright (C) 2002-2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "utils.h" +#include "ardour_message.h" +#include "io_selector.h" +#include "extra_bind.h" +#include "keyboard.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace std; +using namespace Gtk; +using namespace SigC; +using namespace ARDOUR; + +IOSelectorWindow::IOSelectorWindow (Session& sess, IO& ior, bool input, bool can_cancel) + : ArdourDialog ("i/o selector"), + _selector (sess, ior, input), + ok_button (can_cancel ? _("OK"): _("Close")), + cancel_button (_("Cancel")), + rescan_button (_("Rescan")) + +{ + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK); + set_name ("IOSelectorWindow"); + + string title; + if (input) { + title = compose(_("%1 input"), ior.name()); + } else { + title = compose(_("%1 output"), ior.name()); + } + + ok_button.set_name ("IOSelectorButton"); + cancel_button.set_name ("IOSelectorButton"); + rescan_button.set_name ("IOSelectorButton"); + + button_box.set_spacing (5); + button_box.set_border_width (5); + button_box.set_homogeneous (true); + button_box.pack_start (rescan_button); + + if (can_cancel) { + button_box.pack_start (cancel_button); + } + else { + cancel_button.hide(); + } + + button_box.pack_start (ok_button); + + vbox.pack_start (_selector); + vbox.pack_start (button_box, false, false); + + ok_button.clicked.connect (slot (*this, &IOSelectorWindow::accept)); + cancel_button.clicked.connect (slot (*this, &IOSelectorWindow::cancel)); + rescan_button.clicked.connect (slot (*this, &IOSelectorWindow::rescan)); + + set_title (title); + set_position (GTK_WIN_POS_MOUSE); + add (vbox); + + delete_event.connect (bind (slot (just_hide_it), reinterpret_cast (this))); +} + +IOSelectorWindow::~IOSelectorWindow() +{ +} + +void +IOSelectorWindow::rescan () +{ + _selector.redisplay (); +} + +void +IOSelectorWindow::cancel () +{ + _selector.Finished(IOSelector::Cancelled); + hide (); +} + +void +IOSelectorWindow::accept () +{ + _selector.Finished(IOSelector::Accepted); + hide (); +} + + +gint +IOSelectorWindow::map_event_impl (GdkEventAny *ev) +{ + _selector.redisplay (); + return Window::map_event_impl (ev); +} + +/************************* + The IO Selector "widget" + *************************/ + +IOSelector::IOSelector (Session& sess, IO& ior, bool input) + : session (sess), + io (ior), + for_input (input), + port_frame (for_input? _("Inputs") : _("Outputs")), + add_port_button (for_input? _("Add Input") : _("Add Output")), + remove_port_button (for_input? _("Remove Input") : _("Remove Output")), + clear_connections_button (_("Disconnect All")) +{ + selected_port = 0; + + notebook.set_name ("IOSelectorNotebook"); + notebook.set_usize (-1, 125); + + clear_connections_button.set_name ("IOSelectorButton"); + add_port_button.set_name ("IOSelectorButton"); + remove_port_button.set_name ("IOSelectorButton"); + + selector_frame.set_name ("IOSelectorFrame"); + port_frame.set_name ("IOSelectorFrame"); + + selector_frame.set_label (_("Available connections")); + + selector_button_box.set_spacing (5); + selector_button_box.set_border_width (5); + + selector_box.set_spacing (5); + selector_box.set_border_width (5); + selector_box.pack_start (notebook); + selector_box.pack_start (selector_button_box, false, false); + + selector_frame.add (selector_box); + + port_box.set_spacing (5); + port_box.set_border_width (5); + + port_display_scroller.set_name ("IOSelectorNotebook"); + port_display_scroller.set_border_width (0); + port_display_scroller.set_usize (-1, 170); + port_display_scroller.add_with_viewport (port_box); + port_display_scroller.set_policy (GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + + port_button_box.set_spacing (5); + port_button_box.set_border_width (5); + + port_button_box.pack_start (add_port_button, false, false); + + if (for_input) { + if (io.input_maximum() < 0 || io.input_maximum() > (int) io.n_inputs()) { + add_port_button.set_sensitive (true); + } else { + add_port_button.set_sensitive (false); + } + + } else { + if (io.output_maximum() < 0 || io.output_maximum() > (int) io.n_outputs()) { + add_port_button.set_sensitive (true); + } else { + add_port_button.set_sensitive (false); + } + + } + + port_button_box.pack_start (remove_port_button, false, false); + + if (for_input) { + if (io.input_minimum() < 0 || io.input_minimum() < (int) io.n_inputs()) { + remove_port_button.set_sensitive (true); + } else { + remove_port_button.set_sensitive (false); + } + + } else { + if (io.output_minimum() < 0 || io.output_minimum() < (int) io.n_outputs()) { + remove_port_button.set_sensitive (true); + } else { + remove_port_button.set_sensitive (false); + } + } + + port_button_box.pack_start (clear_connections_button, false, false); + + port_and_button_box.set_border_width (5); + port_and_button_box.pack_start (port_button_box, false, false); + port_and_button_box.pack_start (port_display_scroller); + + port_frame.add (port_and_button_box); + + port_and_selector_box.set_spacing (5); + port_and_selector_box.pack_start (port_frame); + port_and_selector_box.pack_start (selector_frame); + + set_spacing (5); + set_border_width (5); + pack_start (port_and_selector_box); + + rescan(); + display_ports (); + + clear_connections_button.clicked.connect (slot (*this, &IOSelector::clear_connections)); + + add_port_button.clicked.connect (slot (*this, &IOSelector::add_port)); + remove_port_button.clicked.connect (slot (*this, &IOSelector::remove_port)); + + if (for_input) { + io.input_changed.connect (slot (*this, &IOSelector::ports_changed)); + } else { + io.output_changed.connect (slot (*this, &IOSelector::ports_changed)); + } + + io.name_changed.connect (slot (*this, &IOSelector::name_changed)); +} + +IOSelector::~IOSelector () +{ +} + +void +IOSelector::name_changed (void* src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &IOSelector::name_changed), src)); + + display_ports (); +} + +void +IOSelector::clear_connections () +{ + if (for_input) { + io.disconnect_inputs (this); + } else { + io.disconnect_outputs (this); + } +} + +void +IOSelector::rescan () +{ + using namespace Notebook_Helpers; + using namespace CList_Helpers; + + typedef map > > PortMap; + PortMap portmap; + const char **ports; + PageList& pages = notebook.pages(); + gint current_page; + vector rowdata; + + current_page = notebook.get_current_page_num (); + pages.clear (); + + /* get relevant current JACK ports */ + + ports = session.engine().get_ports ("", JACK_DEFAULT_AUDIO_TYPE, for_input?JackPortIsOutput:JackPortIsInput); + + if (ports == 0) { + return; + } + + /* find all the client names and group their ports into a list-by-client */ + + for (int n = 0; ports[n]; ++n) { + + pair > > newpair; + pair strpair; + pair result; + + string str = ports[n]; + string::size_type pos; + string portname; + + pos = str.find (':'); + + newpair.first = str.substr (0, pos); + portname = str.substr (pos+1); + + /* this may or may not succeed at actually inserting. + we don't care, however: we just want an iterator + that gives us either the inserted element or + the existing one with the same name. + */ + + result = portmap.insert (newpair); + + strpair.first = portname; + strpair.second = str; + + result.first->second.push_back (strpair); + } + + PortMap::iterator i; + + for (i = portmap.begin(); i != portmap.end(); ++i) { + + Box *client_box = manage (new VBox); + Gtk::CList *client_port_display = manage (new Gtk::CList (1)); + ScrolledWindow *scroller = manage (new ScrolledWindow); + + scroller->add_with_viewport (*client_port_display); + scroller->set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + client_box->pack_start (*scroller); + + client_port_display->set_selection_mode (GTK_SELECTION_BROWSE); + client_port_display->set_name ("IOSelectorList"); + + for (vector >::iterator s = i->second.begin(); s != i->second.end(); ++s) { + + rowdata.clear (); + rowdata.push_back (s->first); + client_port_display->rows().push_back (rowdata); + client_port_display->rows().back().set_data (g_strdup (s->second.c_str()), free); + } + + client_port_display->columns_autosize (); + client_port_display->select_row.connect (bind (slot (*this, &IOSelector::port_selection_handler), client_port_display)); + + Label *tab_label = manage (new Label); + + tab_label->set_name ("IOSelectorNotebookTab"); + tab_label->set_text ((*i).first); + + pages.push_back (TabElem (*client_box, *tab_label)); + } + + notebook.set_page (current_page); + notebook.show.connect (bind (slot (notebook, &Notebook::set_page), current_page)); + selector_box.show_all (); +} + +void +IOSelector::display_ports () +{ + CList *clist = 0; + CList *firstclist = 0; + CList *selected_port_list = 0; + + { + LockMonitor lm (port_display_lock, __LINE__, __FILE__); + Port *port; + uint32_t limit; + + if (for_input) { + limit = io.n_inputs(); + } else { + limit = io.n_outputs(); + } + + for (slist::iterator i = port_displays.begin(); i != port_displays.end(); ) { + + slist::iterator tmp; + + tmp = i; + ++tmp; + + port_box.remove (**i); + delete *i; + port_displays.erase (i); + + i = tmp; + } + + for (uint32_t n = 0; n < limit; ++n) { + const gchar *title[1]; + string really_short_name; + + if (for_input) { + port = io.input (n); + } else { + port = io.output (n); + } + + /* we know there is '/' because we put it there */ + + really_short_name = port->short_name(); + really_short_name = really_short_name.substr (really_short_name.find ('/') + 1); + + title[0] = really_short_name.c_str(); + clist = new CList (1, title); + if (!firstclist) { + firstclist = clist; + } + + port_displays.insert (port_displays.end(), clist); + port_box.pack_start (*clist); + + clist->set_data (_("port"), port); + + /* XXX THIS IS A DIGUSTING AND DIRTY HACK, FORCED UPON US BECAUSE + GtkCList DOESN'T PROVIDE ANY WAY TO CONNECT TO BUTTON_PRESS_EVENTS + FOR THE COLUMN TITLE BUTTON. + */ + + clist->column(0).get_widget(); // force the column title button to be created + GtkButton *b = GTK_BUTTON(clist->gtkobj()->column[0].button); // no API to access this + Gtk::Button *B = wrap (b); // make C++ signal handling easier. + + clist->column_titles_show (); + clist->column_titles_active (); + + if (for_input) { + + if (io.input_maximum() == 1) { + selected_port = port; + selected_port_list = clist; + } else { + if (port == selected_port) { + selected_port_list = clist; + } + } + + B->button_release_event.connect + (bind (slot (*this, &IOSelector::port_column_button_release), clist)); + + } else { + + if (io.output_maximum() == 1) { + selected_port = port; + selected_port_list = clist; + } else { + if (port == selected_port) { + selected_port_list = clist; + } + } + + B->button_release_event.connect + (bind (slot (*this, &IOSelector::port_column_button_release), clist)); + } + + clist->set_name ("IOSelectorPortList"); + clist->set_selection_mode (GTK_SELECTION_SINGLE); + clist->set_shadow_type (GTK_SHADOW_IN); + clist->set_usize (-1, 75); + + /* now fill the clist with the current connections */ + + const char **connections = port->get_connections (); + + if (connections) { + + for (uint32_t c = 0; connections[c]; ++c) { + + const gchar *txt[1]; + + txt[0] = connections[c]; + + clist->rows().push_back (txt); + } + + free (connections); + } + + clist->columns_autosize (); + clist->button_release_event.connect (bind (slot (*this, &IOSelector::connection_click), clist)); + } + + port_box.show_all (); + + if (selected_port_list) { + selected_port_list->click_column(0); + selected_port_list->set_name ("IOSelectorPortListSelected"); + for (slist::iterator i = port_displays.begin(); i != port_displays.end(); ++i) { + if (*i != selected_port_list) { + (*i)->set_name ("IOSelectorPortList"); + (*i)->queue_draw (); + } + } + } else { + selected_port = 0; + selector_box.hide_all (); + } + } + + if (selected_port_list) { + select_clist (selected_port_list); + } else if (firstclist) { + // select first + select_clist (firstclist); + } +} + +void +IOSelector::port_selection_handler (gint row, gint col, GdkEvent *ev, Gtk::CList *clist) +{ + using namespace CList_Helpers; + int status; + + if (selected_port == 0) { + return; + } + + string other_port_name = (char *) clist->rows()[row].get_data(); + + if (for_input) { + if ((status = io.connect_input (selected_port, other_port_name, this)) == 0) { + Port *p = session.engine().get_port_by_name (other_port_name); + p->enable_metering(); + } + } else { + status = io.connect_output (selected_port, other_port_name, this); + } + + if (status == 0) { + select_next_clist (); + } +} + +void +IOSelector::ports_changed (IOChange change, void *src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &IOSelector::ports_changed), change, src)); + + display_ports (); +} + +void +IOSelector::add_port () +{ + /* add a new port, then hide the button if we're up to the maximum allowed */ + + if (for_input) { + + + try { + + io.add_input_port ("", this); + } + + catch (AudioEngine::PortRegistrationFailure& err) { + ArdourMessage msg (0, X_("noport dialog"), + _("There are no more JACK ports available.")); + } + + if (io.input_maximum() >= 0 && io.input_maximum() <= (int) io.n_inputs()) { + add_port_button.set_sensitive (false); + } + + if (io.input_minimum() < (int) io.n_inputs()) { + remove_port_button.set_sensitive (true); + } + + } else { + + try { + io.add_output_port ("", this); + } + + catch (AudioEngine::PortRegistrationFailure& err) { + ArdourMessage msg (0, X_("noport dialog"), + _("There are no more JACK ports available.")); + } + + if (io.output_maximum() >= 0 && io.output_maximum() <= (int) io.n_outputs()) { + add_port_button.set_sensitive (false); + } + } +} + +void +IOSelector::remove_port () +{ + // always remove last port + uint32_t nports; + + if (for_input) { + if ((nports = io.n_inputs()) > 0) { + io.remove_input_port (io.input(nports-1), this); + } + if (io.input_minimum() == (int) io.n_inputs()) { + remove_port_button.set_sensitive (false); + } + } else { + if ((nports = io.n_outputs()) > 0) { + io.remove_output_port (io.output(nports-1), this); + } + } +} + +gint +IOSelector::remove_port_when_idle (Port *port) +{ + if (for_input) { + io.remove_input_port (port, this); + } else { + io.remove_output_port (port, this); + } + + return FALSE; +} + +gint +IOSelector::port_column_button_release (GdkEventButton *event, CList *clist) +{ + if (Keyboard::is_delete_event (event)) { + Port* port; + { + LockMonitor lm (port_display_lock, __LINE__, __FILE__); + + port = reinterpret_cast (clist->get_data (_("port"))); + + if (port == selected_port) { + selected_port = 0; + clist->set_name ("IOSelectorPortList"); + clist->queue_draw(); + } + } + + /* remove the port when idle - if we do it here, we will destroy the widget + for whom we are handling an event. not good. + */ + + Gtk::Main::idle.connect (bind (slot (*this, &IOSelector::remove_port_when_idle), port)); + + } else { + select_clist(clist); + } + + return TRUE; +} + +void +IOSelector::select_next_clist () +{ + slist::iterator next; + + for (slist::iterator i = port_displays.begin(); i != port_displays.end(); ++i) { + + if ((*i)->get_name() == "IOSelectorPortListSelected") { + + ++i; + + if (i == port_displays.end()) { + select_clist (port_displays.front()); + } else { + select_clist (*i); + } + + break; + } + } +} + +void +IOSelector::select_clist(Gtk::CList* clist) +{ + /* Gack. CList's don't respond visually to a change + in their state, so rename them to force a style + switch. + */ + LockMonitor lm (port_display_lock, __LINE__, __FILE__); + Port* port = reinterpret_cast (clist->get_data (_("port"))); + + if (port != selected_port) { + selected_port = port; + + clist->set_name ("IOSelectorPortListSelected"); + + for (slist::iterator i = port_displays.begin(); i != port_displays.end(); ++i) { + if (*i != clist) { + (*i)->set_name ("IOSelectorPortList"); + (*i)->queue_draw (); + } + } + selector_box.show_all (); + } +} + +gint +IOSelector::connection_click (GdkEventButton *ev, CList *clist) +{ + gint row, col; + + /* only handle button1 events here */ + + if (ev->button != 1) { + return FALSE; + } + + if (clist->get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) { + return FALSE; + } + + if (row < 0 || col < 0) { + return FALSE; + } + + Port *port = reinterpret_cast (clist->get_data (_("port"))); + string connected_port_name = clist->cell(row,col).get_text (); + + if (for_input) { + Port *p = session.engine().get_port_by_name (connected_port_name); + p->disable_metering(); + io.disconnect_input (port, connected_port_name, this); + } else { + io.disconnect_output (port, connected_port_name, this); + } + + return TRUE; +} + +void +IOSelector::redisplay () +{ + display_ports (); + + if (for_input) { + if (io.input_maximum() != 0) { + rescan (); + } + } else { + if (io.output_maximum() != 0) { + rescan(); + } + } +} + +PortInsertUI::PortInsertUI (Session& sess, PortInsert& pi) + : input_selector (sess, pi, true), + output_selector (sess, pi, false) +{ + hbox.pack_start (output_selector, true, true); + hbox.pack_start (input_selector, true, true); + + + pack_start (hbox); +} + +void +PortInsertUI::redisplay() +{ + + input_selector.redisplay(); + output_selector.redisplay(); +} + +void +PortInsertUI::finished(IOSelector::Result r) +{ + input_selector.Finished (r); + output_selector.Finished (r); +} + + +PortInsertWindow::PortInsertWindow (Session& sess, PortInsert& pi, bool can_cancel) + : ArdourDialog ("port insert dialog"), + _portinsertui(sess, pi), + ok_button (can_cancel ? _("OK"): _("Close")), + cancel_button (_("Cancel")), + rescan_button (_("Rescan")) +{ + + set_name ("IOSelectorWindow"); + string title = _("ardour: "); + title += pi.name(); + set_title (title); + + ok_button.set_name ("IOSelectorButton"); + cancel_button.set_name ("IOSelectorButton"); + rescan_button.set_name ("IOSelectorButton"); + + button_box.set_spacing (5); + button_box.set_border_width (5); + button_box.set_homogeneous (true); + button_box.pack_start (rescan_button); + if (can_cancel) { + button_box.pack_start (cancel_button); + } + else { + cancel_button.hide(); + } + button_box.pack_start (ok_button); + + vbox.pack_start (_portinsertui); + vbox.pack_start (button_box, false, false); + + add (vbox); + + ok_button.clicked.connect (slot (*this, &PortInsertWindow::accept)); + cancel_button.clicked.connect (slot (*this, &PortInsertWindow::cancel)); + rescan_button.clicked.connect (slot (*this, &PortInsertWindow::rescan)); + + delete_event.connect (bind (slot (just_hide_it), reinterpret_cast (this))); + pi.GoingAway.connect (slot (*this, &PortInsertWindow::plugin_going_away)); +} + +void +PortInsertWindow::plugin_going_away (ARDOUR::Redirect* ignored) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &PortInsertWindow::plugin_going_away), ignored)); + + delete_when_idle (this); +} + +gint +PortInsertWindow::map_event_impl (GdkEventAny *ev) +{ + _portinsertui.redisplay (); + return Window::map_event_impl (ev); +} + + +void +PortInsertWindow::rescan () +{ + _portinsertui.redisplay(); +} + +void +PortInsertWindow::cancel () +{ + _portinsertui.finished(IOSelector::Cancelled); + hide (); +} + +void +PortInsertWindow::accept () +{ + _portinsertui.finished(IOSelector::Accepted); + hide (); +} diff --git a/gtk2_ardour/io_selector.h b/gtk2_ardour/io_selector.h new file mode 100644 index 0000000000..5187f64689 --- /dev/null +++ b/gtk2_ardour/io_selector.h @@ -0,0 +1,182 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_ui_io_selector_h__ +#define __ardour_ui_io_selector_h__ + +#if __GNUC__ >= 3 +#include +using __gnu_cxx::slist; +#else +#include +#endif + +#include +#include + +#include + +namespace ARDOUR { + class IO; + class Session; + class PortInsert; + class Port; + class Redirect; +} + +class IOSelector : public Gtk::VBox { + public: + IOSelector (ARDOUR::Session&, ARDOUR::IO&, bool for_input); + ~IOSelector (); + + void redisplay (); + + enum Result { + Cancelled, + Accepted + }; + + SigC::Signal1 Finished; + + protected: + ARDOUR::Session& session; + + private: + ARDOUR::IO& io; + bool for_input; + ARDOUR::Port *selected_port; + + Gtk::VBox main_box; + Gtk::HBox port_and_selector_box; + + /* client/port selection */ + + Gtk::Notebook notebook; + Gtk::Frame selector_frame; + Gtk::VBox selector_box; + Gtk::HBox selector_button_box; + + /* ports */ + + Gtk::VBox port_box; + Gtk::HBox port_button_box; + Gtk::VBox port_and_button_box; + Gtk::Frame port_frame; + Gtk::Button add_port_button; + Gtk::Button remove_port_button; + Gtk::Button clear_connections_button; + Gtk::ScrolledWindow port_display_scroller; + + PBD::Lock port_display_lock; + slist port_displays; + void display_ports (); + + void rescan (); + void clear_connections (); + + void port_selection_handler (gint row, gint col, GdkEvent *ev, Gtk::CList *); + + void ports_changed (ARDOUR::IOChange, void *); + void name_changed (void*); + + void add_port (); + void remove_port (); + gint remove_port_when_idle (ARDOUR::Port *); + + gint port_column_button_release (GdkEventButton*, Gtk::CList*); + gint connection_click (GdkEventButton *, Gtk::CList *clist); + + void select_clist(Gtk::CList*); + void select_next_clist (); +}; + +class IOSelectorWindow : public ArdourDialog +{ + public: + IOSelectorWindow (ARDOUR::Session&, ARDOUR::IO&, bool for_input, bool can_cancel=false); + ~IOSelectorWindow (); + + IOSelector& selector() { return _selector; } + + protected: + gint map_event_impl (GdkEventAny *); + + private: + IOSelector _selector; + + Gtk::VBox vbox; + + /* overall operation buttons */ + + Gtk::Button ok_button; + Gtk::Button cancel_button; + Gtk::Button rescan_button; + Gtk::HBox button_box; + + void rescan (); + void cancel (); + void accept (); +}; + + +class PortInsertUI : public Gtk::VBox +{ + public: + PortInsertUI (ARDOUR::Session&, ARDOUR::PortInsert&); + + void redisplay (); + void finished (IOSelector::Result); + + private: + + Gtk::HBox hbox; + IOSelector input_selector; + IOSelector output_selector; + +}; + +class PortInsertWindow : public ArdourDialog +{ + public: + PortInsertWindow (ARDOUR::Session&, ARDOUR::PortInsert&, bool can_cancel=false); + + protected: + gint map_event_impl (GdkEventAny *); + + private: + + PortInsertUI _portinsertui; + Gtk::VBox vbox; + + Gtk::Button ok_button; + Gtk::Button cancel_button; + Gtk::Button rescan_button; + Gtk::Frame button_frame; + Gtk::HBox button_box; + + void rescan (); + void cancel (); + void accept (); + + void plugin_going_away (ARDOUR::Redirect*); +}; + + +#endif /* __ardour_ui_io_selector_h__ */ diff --git a/gtk2_ardour/keyboard.cc b/gtk2_ardour/keyboard.cc new file mode 100644 index 0000000000..e0d2314b2f --- /dev/null +++ b/gtk2_ardour/keyboard.cc @@ -0,0 +1,1006 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include "ardour_ui.h" + +#include +#include + +#include + +#include +#include +#include +#include + +#include "keyboard.h" +#include "keyboard_target.h" +#include "ardour_dialog.h" +#include "gui_thread.h" + +#include "i18n.h" + +#define KBD_DEBUG 1 +bool debug_keyboard = false; + +guint Keyboard::edit_but = 3; +guint Keyboard::edit_mod = GDK_CONTROL_MASK; +guint Keyboard::delete_but = 3; +guint Keyboard::delete_mod = GDK_SHIFT_MASK; +guint Keyboard::snap_mod = GDK_MOD3_MASK; + +uint32_t Keyboard::Control = GDK_CONTROL_MASK; +uint32_t Keyboard::Shift = GDK_SHIFT_MASK; +uint32_t Keyboard::Alt = GDK_MOD1_MASK; +uint32_t Keyboard::Meta = GDK_MOD2_MASK; + +Keyboard* Keyboard::_the_keyboard = 0; + +/* set this to initially contain the modifiers we care about, then track changes in ::set_edit_modifier() etc. */ + +GdkModifierType Keyboard::RelevantModifierKeyMask = + GdkModifierType (GDK_SHIFT_MASK|GDK_CONTROL_MASK|GDK_MOD3_MASK); + + +Keyboard::Keyboard () +{ + if (_the_keyboard == 0) { + _the_keyboard = this; + } + + target = 0; + default_target = 0; + _queue_events = false; + _flush_queue = false; + playback_ignore_count = 0; + focus_allowed = false; + collecting_prefix = false; + current_dialog = 0; + + get_modifier_masks (); + + snooper_id = gtk_key_snooper_install (_snooper, (gpointer) this); + + /* some global key actions */ + + KeyboardTarget::add_action ("close-dialog", slot (*this, &Keyboard::close_current_dialog)); + + XMLNode* node = ARDOUR_UI::instance()->keyboard_settings(); + set_state (*node); +} + +Keyboard::~Keyboard () +{ + gtk_key_snooper_remove (snooper_id); + delete [] modifier_masks; +} + +XMLNode& +Keyboard::get_state (void) +{ + XMLNode* node = new XMLNode ("Keyboard"); + char buf[32]; + + snprintf (buf, sizeof (buf), "%d", edit_but); + node->add_property ("edit-button", buf); + snprintf (buf, sizeof (buf), "%d", edit_mod); + node->add_property ("edit-modifier", buf); + snprintf (buf, sizeof (buf), "%d", delete_but); + node->add_property ("delete-button", buf); + snprintf (buf, sizeof (buf), "%d", delete_mod); + node->add_property ("delete-modifier", buf); + snprintf (buf, sizeof (buf), "%d", snap_mod); + node->add_property ("snap-modifier", buf); + + return *node; +} + +int +Keyboard::set_state (const XMLNode& node) +{ + const XMLProperty* prop; + + if ((prop = node.property ("edit-button")) != 0) { + sscanf (prop->value().c_str(), "%d", &edit_but); + } + + if ((prop = node.property ("edit-modifier")) != 0) { + sscanf (prop->value().c_str(), "%d", &edit_mod); + } + + if ((prop = node.property ("delete-button")) != 0) { + sscanf (prop->value().c_str(), "%d", &delete_but); + } + + if ((prop = node.property ("delete-modifier")) != 0) { + sscanf (prop->value().c_str(), "%d", &delete_mod); + } + + if ((prop = node.property ("snap-modifier")) != 0) { + sscanf (prop->value().c_str(), "%d", &snap_mod); + } + + return 0; +} + +gint +Keyboard::_snooper (GtkWidget *widget, GdkEventKey *event, gpointer data) +{ + return ((Keyboard *) data)->snooper (widget, event); +} + +gint +Keyboard::snooper (GtkWidget *widget, GdkEventKey *event) +{ + bool handled = false; + uint32_t keyval; + +#if KBD_DEBUG + if (debug_keyboard) { + cerr << "snoop widget " << widget << " key " << event->keyval << " type: " << event->type + << " focus allowed? " << focus_allowed << " current dialog = " << current_dialog + << endl; + } +#endif + + /* Only allow key events to propagate to the + usual GTK model when specifically allowed. + Returning FALSE here does that. + */ + + if (focus_allowed) { + return FALSE; + } + + if (event->keyval == GDK_Shift_R) { + keyval = GDK_Shift_L; + + } else if (event->keyval == GDK_Control_R) { + keyval = GDK_Control_L; + + } else { + keyval = event->keyval; + } + + + if (event->type == GDK_KEY_PRESS) { + bool was_prefix = false; + + if (collecting_prefix) { + switch (keyval) { + case GDK_0: + current_prefix += '0'; + was_prefix = true; + break; + case GDK_1: + current_prefix += '1'; + was_prefix = true; + break; + case GDK_2: + current_prefix += '2'; + was_prefix = true; + break; + case GDK_3: + current_prefix += '3'; + was_prefix = true; + break; + case GDK_4: + current_prefix += '4'; + was_prefix = true; + break; + case GDK_5: + current_prefix += '5'; + was_prefix = true; + break; + case GDK_6: + current_prefix += '6'; + was_prefix = true; + break; + case GDK_7: + current_prefix += '7'; + was_prefix = true; + break; + case GDK_8: + current_prefix += '8'; + was_prefix = true; + break; + case GDK_9: + current_prefix += '9'; + was_prefix = true; + break; + case GDK_period: + current_prefix += '.'; + was_prefix = true; + break; + default: + was_prefix = false; + collecting_prefix = false; + break; + } + } + + if (find (state.begin(), state.end(), keyval) == state.end()) { + state.push_back (keyval); + sort (state.begin(), state.end()); + } + +#if KBD_DEBUG + if (debug_keyboard) { + cerr << "STATE: "; + for (State::iterator i = state.begin(); i != state.end(); ++i) { + cerr << (*i) << ' '; + } + cerr << endl; + } +#endif + + if (!was_prefix) { + + bool old_collecting_prefix = collecting_prefix; + + if (target) { +#if KBD_DEBUG + if (debug_keyboard) { + cerr << "PRESS: delivering to target " << target << endl; + } +#endif + target->key_press_event (event, state, handled); + } + + if (!handled && default_target) { +#if KBD_DEBUG + if (debug_keyboard) { + cerr << "PRESS: not handled, delivering to default target " << default_target << endl; + } +#endif + default_target->key_press_event (event, state, handled); + } + +#if KBD_DEBUG + if (debug_keyboard) { + cerr << "PRESS: handled ? " << handled << endl; + } +#endif + + if (handled) { + + /* don't reset collecting prefix is start_prefix() + was called by the handler. + */ + + if (collecting_prefix == old_collecting_prefix) { + collecting_prefix = false; + current_prefix = ""; + } + } + } + + } else if (event->type == GDK_KEY_RELEASE) { + + State::iterator i; + + if ((i = find (state.begin(), state.end(), keyval)) != state.end()) { + state.erase (i); + sort (state.begin(), state.end()); + } + + if (target) { +#if KBD_DEBUG + if (debug_keyboard) { + cerr << "RELEASE: delivering to target " << target << endl; + } +#endif + target->key_release_event (event, state); + } + + if (default_target) { +#if KBD_DEBUG + if (debug_keyboard) { + cerr << "RELEASE: delivering to default target " << default_target << endl; + } +#endif + default_target->key_release_event (event, state); + } + } + + return TRUE; +} + +bool +Keyboard::key_is_down (uint32_t keyval) +{ + return find (state.begin(), state.end(), keyval) != state.end(); +} + +void +Keyboard::set_target (KeyboardTarget *kt) +{ + /* XXX possible thread issues here */ + target = kt; +} + +void +Keyboard::maybe_unset_target (KeyboardTarget* kt) +{ + if (target == kt) { + target = 0; + } +} + +void +Keyboard::set_default_target (KeyboardTarget *kt) +{ + /* XXX possible thread issues here */ + + default_target = kt; +} + +void +Keyboard::allow_focus (bool yn) +{ + focus_allowed = yn; +} + +Keyboard::State +Keyboard::translate_key_name (const string& name) + +{ + string::size_type i; + string::size_type len; + bool at_end; + string::size_type hyphen; + string keyname; + string whatevers_left; + State result; + guint keycode; + + i = 0; + len = name.length(); + at_end = (len == 0); + + while (!at_end) { + + whatevers_left = name.substr (i); + + if ((hyphen = whatevers_left.find_first_of ('-')) == string::npos) { + + /* no hyphen, so use the whole thing */ + + keyname = whatevers_left; + at_end = true; + + } else { + + /* There is a hyphen. */ + + if (hyphen == 0 && whatevers_left.length() == 1) { + /* its the first and only character */ + + keyname = "-"; + at_end = true; + + } else { + + /* use the text before the hypen */ + + keyname = whatevers_left.substr (0, hyphen); + + if (hyphen == len - 1) { + at_end = true; + } else { + i += hyphen + 1; + at_end = (i >= len); + } + } + } + + if (keyname.length() == 1 && isupper (keyname[0])) { + result.push_back (GDK_Shift_L); + } + + if ((keycode = gdk_keyval_from_name(get_real_keyname (keyname).c_str())) == GDK_VoidSymbol) { + error << compose(_("KeyboardTarget: keyname \"%1\" is unknown."), keyname) << endmsg; + result.clear(); + return result; + } + + result.push_back (keycode); + } + + sort (result.begin(), result.end()); + + return result; +} + +string +Keyboard::get_real_keyname (const string& name) +{ + + if (name == "Control" || name == "Ctrl") { + return "Control_L"; + } + if (name == "Meta" || name == "MetaL") { + return "Meta_L"; + } + if (name == "MetaR") { + return "Meta_R"; + } + if (name == "Alt" || name == "AltL") { + return "Alt_L"; + } + if (name == "AltR") { + return "Alt_R"; + } + if (name == "Shift") { + return "Shift_L"; + } + if (name == "Shift_R") { + return "Shift_L"; + } + if (name == " ") { + return "space"; + } + if (name == "!") { + return "exclam"; + } + if (name == "\"") { + return "quotedbl"; + } + if (name == "#") { + return "numbersign"; + } + if (name == "$") { + return "dollar"; + } + if (name == "%") { + return "percent"; + } + if (name == "&") { + return "ampersand"; + } + if (name == "'") { + return "apostrophe"; + } + if (name == "'") { + return "quoteright"; + } + if (name == "(") { + return "parenleft"; + } + if (name == ")") { + return "parenright"; + } + if (name == "*") { + return "asterisk"; + } + if (name == "+") { + return "plus"; + } + if (name == ",") { + return "comma"; + } + if (name == "-") { + return "minus"; + } + if (name == ".") { + return "period"; + } + if (name == "/") { + return "slash"; + } + if (name == ":") { + return "colon"; + } + if (name == ";") { + return "semicolon"; + } + if (name == "<") { + return "less"; + } + if (name == "=") { + return "equal"; + } + if (name == ">") { + return "greater"; + } + if (name == "?") { + return "question"; + } + if (name == "@") { + return "at"; + } + if (name == "[") { + return "bracketleft"; + } + if (name == "\\") { + return "backslash"; + } + if (name == "]") { + return "bracketright"; + } + if (name == "^") { + return "asciicircum"; + } + if (name == "_") { + return "underscore"; + } + if (name == "`") { + return "grave"; + } + if (name == "`") { + return "quoteleft"; + } + if (name == "{") { + return "braceleft"; + } + if (name == "|") { + return "bar"; + } + if (name == "}") { + return "braceright"; + } + if (name == "~") { + return "asciitilde"; + } + + return name; +} + +int +Keyboard::get_prefix (float& val, bool& was_floating) +{ + if (current_prefix.length()) { + if (current_prefix.find ('.') != string::npos) { + was_floating = true; + } else { + was_floating = false; + } + if (sscanf (current_prefix.c_str(), "%f", &val) == 1) { + return 0; + } + current_prefix = ""; + } + return -1; +} + +void +Keyboard::start_prefix () +{ + collecting_prefix = true; + current_prefix = ""; +} + +void +Keyboard::clear_modifier_state () +{ + modifier_mask = 0; +} + +void +Keyboard::check_modifier_state () +{ + char keys[32]; + int i, j; + + clear_modifier_state (); + XQueryKeymap (GDK_DISPLAY(), keys); + + for (i = 0; i < 32; ++i) { + for (j = 0; j < 8; ++j) { + + if (keys[i] & (1<modifiermap; + + for (i = 0; i < modifiers->max_keypermod; ++i) { /* shift */ + if (*keycode) { + modifier_masks[*keycode] = GDK_SHIFT_MASK; + // cerr << "Shift = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl; + } + keycode++; + } + + for (i = 0; i < modifiers->max_keypermod; ++i) keycode++; /* skip lock */ + + for (i = 0; i < modifiers->max_keypermod; ++i) { /* control */ + if (*keycode) { + modifier_masks[*keycode] = GDK_CONTROL_MASK; + // cerr << "Control = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl; + } + keycode++; + } + + bound = 0; + for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 1 */ + if (*keycode) { + modifier_masks[*keycode] = GDK_MOD1_MASK; + // cerr << "Mod1 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl; + bound++; + } + keycode++; + } +#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS + if (bound > 1) { + warning << compose (_("You have %1 keys bound to \"mod1\""), bound) << endmsg; + } +#endif + bound = 0; + for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod2 */ + if (*keycode) { + modifier_masks[*keycode] = GDK_MOD2_MASK; + check_meta_numlock (*keycode, GDK_MOD2_MASK, "Mod2"); + //cerr << "Mod2 = " << std::hex << (int) *keycode << std::dec << " = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl; + bound++; + } + keycode++; + } +#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS + if (bound > 1) { + warning << compose (_("You have %1 keys bound to \"mod2\""), bound) << endmsg; + } +#endif + bound = 0; + for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod3 */ + if (*keycode) { + modifier_masks[*keycode] = GDK_MOD3_MASK; + check_meta_numlock (*keycode, GDK_MOD3_MASK, "Mod3"); + // cerr << "Mod3 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl; + bound++; + } + keycode++; + } +#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS + if (bound > 1) { + warning << compose (_("You have %1 keys bound to \"mod3\""), bound) << endmsg; + } +#endif + bound = 0; + for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 4 */ + if (*keycode) { + modifier_masks[*keycode] = GDK_MOD4_MASK; + check_meta_numlock (*keycode, GDK_MOD4_MASK, "Mod4"); + // cerr << "Mod4 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl; + bound++; + } + keycode++; + } +#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS + if (bound > 1) { + warning << compose (_("You have %1 keys bound to \"mod4\""), bound) << endmsg; + } +#endif + bound = 0; + for (i = 0; i < modifiers->max_keypermod; ++i) { /* mod 5 */ + if (*keycode) { + modifier_masks[*keycode] = GDK_MOD5_MASK; + check_meta_numlock (*keycode, GDK_MOD5_MASK, "Mod5"); + // cerr << "Mod5 = " << XKeysymToString (XKeycodeToKeysym (GDK_DISPLAY(), *keycode, 0)) << endl; + bound++; + } + keycode++; + } +#ifdef WARN_ABOUT_DUPLICATE_MODIFIERS + if (bound > 1) { + warning << compose (_("You have %1 keys bound to \"mod5\""), bound) << endmsg; + } +#endif + + XFreeModifiermap (modifiers); +} + +gint +Keyboard::enter_window (GdkEventCrossing *ev, KeyboardTarget *kt) +{ + switch (ev->detail) { + case GDK_NOTIFY_INFERIOR: + if (debug_keyboard) { + cerr << "INFERIOR crossing to " << kt->name() << endl; + } + break; + + case GDK_NOTIFY_VIRTUAL: + if (debug_keyboard) { + cerr << "VIRTUAL crossing to " << kt->name() << endl; + } + /* fallthru */ + + default: + if (debug_keyboard) { + cerr << "REAL crossing to " << kt->name() << endl; + cerr << "set current target to " << kt->name() << endl; + } + + set_target (kt); + check_modifier_state (); + } + + return FALSE; +} + +gint +Keyboard::leave_window (GdkEventCrossing *ev) +{ + switch (ev->detail) { + case GDK_NOTIFY_INFERIOR: + if (debug_keyboard) { + cerr << "INFERIOR crossing ... out\n"; + } + break; + + case GDK_NOTIFY_VIRTUAL: + if (debug_keyboard) { + cerr << "VIRTUAL crossing ... out\n"; + } + /* fallthru */ + + default: + if (debug_keyboard) { + cerr << "REAL CROSSING ... out\n"; + cerr << "clearing current target\n"; + } + + set_target (0); + state.clear (); + clear_modifier_state (); + } + return FALSE; + +} + +void +Keyboard::register_target (KeyboardTarget *kt) +{ + /* do not register the default - its not meant to be + an actual window, just a fallback if the current + target for keyboard events doesn't handle an event. + */ + + if (kt->name() == X_("default")) { + return; + } + + kt->window().enter_notify_event.connect (bind (slot (*this, &Keyboard::enter_window), kt)); + kt->window().leave_notify_event.connect (slot (*this, &Keyboard::leave_window)); + + kt->GoingAway.connect (bind (slot (*this, &Keyboard::maybe_unset_target), kt)); + kt->Hiding.connect (bind (slot (*this, &Keyboard::maybe_unset_target), kt)); +} + +void +Keyboard::set_current_dialog (ArdourDialog* dialog) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Keyboard::set_current_dialog), dialog)); + + current_dialog = dialog; + + if (current_dialog) { + + if (find (known_dialogs.begin(), known_dialogs.end(), dialog) == known_dialogs.end()) { + + current_dialog->GoingAway.connect + (bind (slot (*this, &Keyboard::set_current_dialog), + reinterpret_cast(0))); + current_dialog->Hiding.connect + (bind (slot (*this, &Keyboard::set_current_dialog), + reinterpret_cast(0))); + + current_dialog->unmap_event.connect (slot (*this, &Keyboard::current_dialog_vanished)); + + known_dialogs.push_back (dialog); + } + } +} + +gint +Keyboard::current_dialog_vanished (GdkEventAny *ev) +{ + current_dialog = 0; + state.clear (); + focus_allowed = false; + clear_modifier_state (); + current_prefix = ""; + + return FALSE; +} + +void +Keyboard::close_current_dialog () +{ + if (current_dialog) { + current_dialog->hide (); + } +} + +void +Keyboard::set_edit_button (guint but) +{ + edit_but = but; +} + +void +Keyboard::set_edit_modifier (guint mod) +{ + RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~edit_mod); + edit_mod = mod; + RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | edit_mod); +} + +void +Keyboard::set_delete_button (guint but) +{ + delete_but = but; +} + +void +Keyboard::set_delete_modifier (guint mod) +{ + RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~delete_mod); + delete_mod = mod; + RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | delete_mod); +} + +void +Keyboard::set_meta_modifier (guint mod) +{ + /* we don't include Meta in the RelevantModifierKeyMask because its not used + in the same way as snap_mod, delete_mod etc. the only reason we allow it to be + set at all is that X Window has no convention for the keyboard modifier + that Meta should use. Some Linux distributions bind NumLock to Mod2, which + is our default Meta modifier, and this causes severe problems. + */ + Meta = mod; +} + +void +Keyboard::set_snap_modifier (guint mod) +{ + RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask & ~snap_mod); + snap_mod = mod; + RelevantModifierKeyMask = GdkModifierType (RelevantModifierKeyMask | snap_mod); +} + +bool +Keyboard::is_edit_event (GdkEventButton *ev) +{ + return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) && + (ev->button == Keyboard::edit_button()) && + ((ev->state & RelevantModifierKeyMask) == Keyboard::edit_modifier()); +} + +bool +Keyboard::is_delete_event (GdkEventButton *ev) +{ + return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) && + (ev->button == Keyboard::delete_button()) && + ((ev->state & RelevantModifierKeyMask) == Keyboard::delete_modifier()); +} + +bool +Keyboard::is_context_menu_event (GdkEventButton *ev) +{ + return (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_BUTTON_RELEASE) && + (ev->button == 3) && + ((ev->state & RelevantModifierKeyMask) == 0); +} + +bool +Keyboard::no_modifiers_active (guint state) +{ + return (state & RelevantModifierKeyMask) == 0; +} + +bool +Keyboard::modifier_state_contains (guint state, ModifierMask mask) +{ + return (state & mask) == (guint) mask; +} + +bool +Keyboard::modifier_state_equals (guint state, ModifierMask mask) +{ + return (state & RelevantModifierKeyMask) == (guint) mask; +} + +gint +Keyboard::focus_in_handler (GdkEventFocus* ev) +{ + allow_focus (true); + return FALSE; +} + +gint +Keyboard::focus_out_handler (GdkEventFocus* ev) +{ + allow_focus (false); + return FALSE; +} diff --git a/gtk2_ardour/keyboard.h b/gtk2_ardour/keyboard.h new file mode 100644 index 0000000000..d7d527e63e --- /dev/null +++ b/gtk2_ardour/keyboard.h @@ -0,0 +1,153 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_keyboard_h__ +#define __ardour_keyboard_h__ + +#include +#include + +#include +#include + +#include +#include + +using std::vector; +using std::string; + +class KeyboardTarget; +class ArdourDialog; + +class Keyboard : public SigC::Object, Stateful +{ + public: + Keyboard (); + ~Keyboard (); + + XMLNode& get_state (void); + int set_state (const XMLNode&); + + typedef vector State; + + void set_target (KeyboardTarget *); + void set_default_target (KeyboardTarget *); + void allow_focus (bool); + + gint focus_in_handler (GdkEventFocus*); + gint focus_out_handler (GdkEventFocus*); + + int get_prefix(float&, bool& was_floating); + void start_prefix (); + + static State translate_key_name (const string&); + static string get_real_keyname (const string& name); + + void register_target (KeyboardTarget *); + + void set_current_dialog (ArdourDialog*); + void close_current_dialog (); + + typedef uint32_t ModifierMask; + + static uint32_t Control; + static uint32_t Shift; + static uint32_t Alt; + static uint32_t Meta; + + bool key_is_down (uint32_t keyval); + + static GdkModifierType RelevantModifierKeyMask; + + static bool no_modifier_keys_pressed(GdkEventButton* ev) { + return (ev->state & RelevantModifierKeyMask) == 0; + } + + static bool modifier_state_contains (guint state, ModifierMask); + static bool modifier_state_equals (guint state, ModifierMask); + + static bool no_modifiers_active (guint state); + + static void set_meta_modifier (guint); + + static void set_snap_modifier (guint); + static ModifierMask snap_modifier () { return ModifierMask (snap_mod); } + + static guint edit_button() { return edit_but; } + static void set_edit_button (guint); + static guint edit_modifier() { return edit_mod; } + static void set_edit_modifier(guint); + + static guint delete_button() { return delete_but; } + static void set_delete_button(guint); + static guint delete_modifier() { return delete_mod; } + static void set_delete_modifier(guint); + + static bool is_edit_event (GdkEventButton*); + static bool is_delete_event (GdkEventButton*); + static bool is_context_menu_event (GdkEventButton*); + + static Keyboard& the_keyboard() { return *_the_keyboard; } + + private: + static Keyboard* _the_keyboard; + + bool _queue_events; + bool _flush_queue; + guint32 playback_ignore_count; + + guint snooper_id; + State state; + KeyboardTarget* target; + KeyboardTarget* default_target; + bool focus_allowed; + bool collecting_prefix; + string current_prefix; + int* modifier_masks; + int modifier_mask; + int min_keycode; + int max_keycode; + ArdourDialog* current_dialog; + std::vector known_dialogs; + + static guint edit_but; + static guint edit_mod; + static guint delete_but; + static guint delete_mod; + static guint snap_mod; + + static gint _snooper (GtkWidget*, GdkEventKey*, gpointer); + gint snooper (GtkWidget*, GdkEventKey*); + + void maybe_unset_target (KeyboardTarget *); + void queue_event (GdkEventKey*); + void playback_queue (); + void clear_queue (); + void get_modifier_masks (); + void check_modifier_state (); + void clear_modifier_state (); + gint enter_window (GdkEventCrossing*, KeyboardTarget*); + gint leave_window (GdkEventCrossing*); + gint current_dialog_vanished (GdkEventAny*); + + void check_meta_numlock (char keycode, guint mod, string modname); +}; + +#endif /* __ardour_keyboard_h__ */ diff --git a/gtk2_ardour/keyboard_target.cc b/gtk2_ardour/keyboard_target.cc new file mode 100644 index 0000000000..9f92d2f460 --- /dev/null +++ b/gtk2_ardour/keyboard_target.cc @@ -0,0 +1,258 @@ +/* + Copyright (C) 2001-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include "keyboard.h" +#include "keyboard_target.h" + +#include "i18n.h" + +using std::pair; + +KeyboardTarget::ActionMap KeyboardTarget::actions; + +KeyboardTarget::KeyboardTarget (Gtk::Window& win, string name) + : _window (win) +{ + _name = name; + Keyboard::the_keyboard().register_target (this); +} + +KeyboardTarget::~KeyboardTarget () +{ + GoingAway (); +} + +void +KeyboardTarget::key_release_event (GdkEventKey *event, Keyboard::State& state) +{ + // relax +} + +void +KeyboardTarget::key_press_event (GdkEventKey *event, Keyboard::State& state, bool& handled) +{ + KeyMap::iterator result; + + if ((result = keymap.find (state)) != keymap.end()) { + (*result).second (); + handled = true; + } +} + +int +KeyboardTarget::add_binding (string keystring, string action) +{ + KeyMap::iterator existing; + Keyboard::State state; + KeyAction key_action = 0; + + state = Keyboard::translate_key_name (keystring); + + if (keystring.length() == 0) { + error << _("KeyboardTarget: empty string passed to add_binding.") + << endmsg; + return -1; + } + + if (state.size() == 0) { + error << compose(_("KeyboardTarget: no translation found for \"%1\""), keystring) << endmsg; + return -1; + } + + if (find_action (action, key_action)) { + error << compose(_("KeyboardTarget: unknown action \"%1\""), action) << endmsg; + return -1; + } + + /* remove any existing binding */ + + if ((existing = keymap.find (state)) != keymap.end()) { + keymap.erase (existing); + } + + keymap.insert (pair (state, key_action)); + bindings.insert (pair (keystring, action)); + return 0; +} + +string +KeyboardTarget::get_binding (string name) +{ + BindingMap::iterator i; + + for (i = bindings.begin(); i != bindings.end(); ++i) { + + if (i->second == name) { + + /* convert keystring to GTK format */ + + string str = i->first; + string gtkstr; + string::size_type p; + + while (1) { + + if ((p = str.find ('-')) == string::npos || (p == str.length() - 1)) { + break; + } + + gtkstr += '<'; + gtkstr += str.substr (0, p); + gtkstr += '>'; + + str = str.substr (p+1); + + } + + gtkstr += str; + + if (gtkstr.length() == 0) { + return i->first; + } + + return gtkstr; + } + } + return string (); +} + +void +KeyboardTarget::show_all_actions () +{ + ActionMap::iterator i; + + for (i = actions.begin(); i != actions.end(); ++i) { + cout << i->first << endl; + } +} + +int +KeyboardTarget::add_action (string name, KeyAction action) +{ + pair newpair; + pair result; + newpair.first = name; + newpair.second = action; + + result = actions.insert (newpair); + return result.second ? 0 : -1; +} + +int +KeyboardTarget::find_action (string name, KeyAction& action) +{ + map::iterator i; + + if ((i = actions.find (name)) != actions.end()) { + action = i->second; + return 0; + } else { + return -1; + } +} + +int +KeyboardTarget::remove_action (string name) +{ + map::iterator i; + + if ((i = actions.find (name)) != actions.end()) { + actions.erase (i); + return 0; + } else { + return -1; + } +} + +XMLNode& +KeyboardTarget::get_binding_state () const +{ + XMLNode *node = new XMLNode ("context"); + BindingMap::const_iterator i; + + node->add_property ("name", _name); + + for (i = bindings.begin(); i != bindings.end(); ++i) { + XMLNode *child; + + child = new XMLNode ("binding"); + child->add_property ("keys", i->first); + child->add_property ("action", i->second); + node->add_child_nocopy (*child); + } + + return *node; +} + +int +KeyboardTarget::set_binding_state (const XMLNode& node) +{ + XMLNodeList nlist = node.children(); + XMLNodeConstIterator niter; + XMLNode *child_node; + + bindings.clear (); + keymap.clear (); + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + child_node = *niter; + + if (child_node->name() == "context") { + XMLProperty *prop; + + if ((prop = child_node->property ("name")) != 0) { + if (prop->value() == _name) { + return load_bindings (*child_node); + } + } + } + } + + return 0; +} + +int +KeyboardTarget::load_bindings (const XMLNode& node) +{ + XMLNodeList nlist = node.children(); + XMLNodeConstIterator niter; + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + XMLProperty *keys; + XMLProperty *action; + + keys = (*niter)->property ("keys"); + action = (*niter)->property ("action"); + + if (!keys || !action) { + error << _("misformed binding node - ignored") << endmsg; + continue; + } + + add_binding (keys->value(), action->value()); + + } + + return 0; +} + diff --git a/gtk2_ardour/keyboard_target.h b/gtk2_ardour/keyboard_target.h new file mode 100644 index 0000000000..cb76579314 --- /dev/null +++ b/gtk2_ardour/keyboard_target.h @@ -0,0 +1,82 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_keyboard_target_h__ +#define __ardour_keyboard_target_h__ + +#include +#include +#include +#include +#include +#include + +#include "keyboard.h" + +using std::map; +using std::string; + +class KeyboardTarget +{ + public: + KeyboardTarget(Gtk::Window& w, string name); + virtual ~KeyboardTarget(); + + SigC::Signal0 Hiding; + SigC::Signal0 GoingAway; + + typedef SigC::Slot0 KeyAction; + + string name() const { return _name; } + + void key_press_event (GdkEventKey *, Keyboard::State&, bool& handled); + void key_release_event (GdkEventKey *, Keyboard::State&); + + int add_binding (string keys, string name); + string get_binding (string name); /* returns keys bound to name */ + + XMLNode& get_binding_state () const; + int set_binding_state (const XMLNode&); + + static int32_t add_action (string, KeyAction); + static int32_t find_action (string, KeyAction&); + static int32_t remove_action (string); + static void show_all_actions(); + + Gtk::Window& window() const { return _window; } + + protected: + typedef map KeyMap; + typedef map BindingMap; + + KeyMap keymap; + BindingMap bindings; + + private: + typedef map ActionMap; + static ActionMap actions; + string _name; + Gtk::Window& _window; + + int load_bindings (const XMLNode&); +}; + +#endif /* __ardour_keyboard_target_h__ */ + diff --git a/gtk2_ardour/library_ui.cc b/gtk2_ardour/library_ui.cc new file mode 100644 index 0000000000..7e17079e49 --- /dev/null +++ b/gtk2_ardour/library_ui.cc @@ -0,0 +1,1541 @@ +/* + Copyright (C) 2000-2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ardour_ui.h" +#include "public_editor.h" +#include "library_ui.h" +#include "prompter.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; +using namespace Gtk; +using namespace SigC; + +SoundFileSelector::SoundFileSelector () + : ArdourDialog ("sound file selector"), + vbox(false, 4), + sfdb_label(_("Soundfile Library")), + fs_label(_("Filesystem")), + import_box(false, 4), + import_btn (X_("foo")), // force a label + split_channels (_("Split Channels"), 0.0), + info_box (0) +{ + set_title(_("ardour: soundfile selector")); + set_name("SoundFileSelector"); + set_default_size (500, 400); + set_keyboard_input (true); + + add (main_box); + main_box.set_border_width (6); + + main_box.pack_start(vbox, true, true); + vbox.pack_start(notebook, true, true); + vbox.pack_start(import_box, false, false); + + notebook.set_name("SoundFileSelectorNotebook"); + notebook.append_page(sf_browser, fs_label); + notebook.append_page(sfdb_tree, sfdb_label); + + import_box.set_homogeneous (true); + import_box.pack_start(import_btn); + import_box.pack_start (split_channels); + + split_channels.set_active(false); + split_channels.set_sensitive (false); + + delete_event.connect (slot (*this, &ArdourDialog::wm_close_event)); + + import_btn.clicked.connect (slot (*this, &SoundFileSelector::import_btn_clicked)); + + sfdb_tree.group_selected.connect (slot(*this, &SoundFileSelector::sfdb_group_selected)); + sfdb_tree.member_selected.connect (bind (slot(*this, &SoundFileSelector::member_selected), true)); + sf_browser.member_selected.connect (bind (slot(*this, &SoundFileSelector::member_selected), false)); + sf_browser.member_deselected.connect (bind (slot(*this, &SoundFileSelector::member_deselected), false)); + sfdb_tree.deselected.connect (slot(*this, &SoundFileSelector::sfdb_deselected)); + sf_browser.group_selected.connect (slot(*this, &SoundFileSelector::browser_group_selected)); + notebook.switch_page.connect (slot(*this, &SoundFileSelector::page_switched)); +} + +SoundFileSelector::~SoundFileSelector() +{ +} + +void +SoundFileSelector::import_btn_clicked () +{ + vector paths; + + PublicEditor& edit = ARDOUR_UI::instance()->the_editor(); + ARDOUR::Session* sess = edit.current_session(); + if (sess) { + sess->cancel_audition(); + } + + if (sfdb) { + for (list::iterator i = sfdb_tree.selection.begin(); i != sfdb_tree.selection.end(); ++i) { + paths.push_back (Library->get_member_filename (*i)); + } + } else { + for (list::iterator i = sf_browser.selection.begin(); i != sf_browser.selection.end(); ++i) { + paths.push_back ((*i).str); + } + } + + Action (paths, split_channels.get_active()); /* EMIT_SIGNAL */ + + if (sfdb) { + sfdb_tree.clear_selection (); + } else { + sf_browser.clear_selection (); + } + + if (hide_after_action) { + hide (); + Action.clear(); + } + hide_after_action = false; + +} + +void +SoundFileSelector::run (string action, bool multi, bool hide_after) +{ + static_cast(import_btn.get_child())->set_text (action); + import_btn.set_sensitive(false); + + if (multi) { + split_channels.show (); + } else { + split_channels.hide (); + } + + multiable = multi; + hide_after_action = hide_after; + + set_position (GTK_WIN_POS_MOUSE); + ArdourDialog::run (); +} + +void +SoundFileSelector::hide_import_stuff() +{ + import_box.hide_all(); +} + +void +SoundFileSelector::page_switched(Gtk::Notebook_Helpers::Page* page, guint page_num) +{ + if (page_num == 1) { + sfdb = true; + if (!sfdb_tree.selection.empty()) { + member_selected (sfdb_tree.selection.back(), true); + } + } else { + sfdb = false; + if (!sf_browser.selection.empty()) { + member_selected (sf_browser.selection.back().str, false); + } + } +} + +void +SoundFileSelector::sfdb_deselected() +{ + import_btn.set_sensitive(false); +} + +void +SoundFileSelector::browser_group_selected() +{ + sfdb_group_selected(); +} + +void +SoundFileSelector::sfdb_group_selected() +{ + import_btn.set_sensitive(false); + split_channels.set_sensitive(false); + + if (info_box) { + delete info_box; + info_box = 0; + } +} + +void +SoundFileSelector::member_selected(string member, bool sfdb) +{ + if (info_box) { + delete info_box; + info_box = 0; + } + + if (member.empty()) { + return; + } + + try { + info_box = new SoundFileBox(member, sfdb); + } catch (failed_constructor& err) { + /* nothing to do */ + return; + } + + main_box.pack_start (*info_box, false, false); + + import_btn.set_sensitive (true); + + if (multiable) { + split_channels.set_sensitive(true); + } +} + +void +SoundFileSelector::member_deselected (bool sfdb) +{ + bool keep_action_available; + string last; + + if (info_box) { + delete info_box; + info_box = 0; + } + + if (sfdb) { + if ((keep_action_available = !sfdb_tree.selection.empty())) { + last = sfdb_tree.selection.back(); + } + + } else { + if ((keep_action_available = !sf_browser.selection.empty())) { + last = sf_browser.selection.back().str; + } + } + + if (keep_action_available) { + + if (info_box) { + delete info_box; + info_box = 0; + } + + try { + info_box = new SoundFileBox(last, sfdb); + } catch (failed_constructor& err) { + /* nothing to do */ + return; + } + + import_btn.set_sensitive (true); + + if (multiable) { + split_channels.set_sensitive(true); + } + + main_box.pack_start(*info_box, false, false); + } +} + +void +SoundFileSelector::get_result (vector& paths, bool& split) +{ + if (sfdb) { + for (list::iterator i = sfdb_tree.selection.begin(); i != sfdb_tree.selection.end(); ++i) { + paths.push_back (Library->get_member_filename (*i)); + } + } else { + for (list::iterator i = sf_browser.selection.begin(); i != sf_browser.selection.end(); ++i) { + paths.push_back ((*i).str); + } + } + + split = split_channels.get_active(); +} + +SoundFileBrowser::SoundFileBrowser() + : + Gtk::VBox(false, 3) +{ + fs_selector.hide_fileop_buttons(); + fs_selector.set_filename("/"); + + // This is ugly ugly ugly. But gtk1 (and gtk2) don't give us any + // choice. + GtkFileSelection* fs_gtk = fs_selector.gtkobj(); + file_list= Gtk::wrap((GtkCList*)(fs_gtk->file_list)); + + Gtk::VBox* vbox = manage(new Gtk::VBox); + Gtk::HBox* tmphbox = manage(new Gtk::HBox); + Gtk::OptionMenu* option_menu = Gtk::wrap((GtkOptionMenu*)(fs_gtk->history_pulldown)); + option_menu->reparent(*tmphbox); + vbox->pack_start(*tmphbox, false, false); + + /* XXX This interface isn't supported in gtkmm. Redo it with a BoxList& + vbox->set_child_packing(*option_menu, false, false); */ + + Gtk::HBox* hbox = manage(new Gtk::HBox); + Gtk::ScrolledWindow* dir_scroll = manage(new Gtk::ScrolledWindow); + Gtk::ScrolledWindow* file_scroll = manage(new Gtk::ScrolledWindow); + dir_scroll->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + file_scroll->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + Gtk::CList* dir_list = Gtk::wrap((GtkCList*)(fs_gtk->dir_list)); + + dir_list->reparent(*dir_scroll); + file_list->reparent(*file_scroll); + file_list->set_selection_mode (GTK_SELECTION_MULTIPLE); + hbox->pack_start(*dir_scroll); + hbox->pack_start(*file_scroll); + vbox->pack_start(*hbox, true, true); + + Gtk::VBox* tmpvbox = manage(new Gtk::VBox); + + Gtk::Label* selection_text = Gtk::wrap((GtkLabel*)(fs_gtk->selection_text)); + selection_text->reparent(*tmpvbox); + Gtk::Entry* selection_entry= Gtk::wrap((GtkEntry*)(fs_gtk->selection_entry)); + selection_entry->reparent(*tmpvbox); + vbox->pack_start(*tmpvbox, false, false); + + pack_start(*vbox, true, true); + + dir_list->select_row.connect(slot (*this, &SoundFileBrowser::dir_list_selected)); + file_list->select_row.connect(slot (*this, &SoundFileBrowser::file_list_selected)); + file_list->unselect_row.connect(slot (*this, &SoundFileBrowser::file_list_deselected)); + + dir_list->set_name("SoundFileBrowserList"); + file_list->set_name("SoundFileBrowserList"); +} + +SoundFileBrowser::~SoundFileBrowser() +{ +} + +void +SoundFileBrowser::clear_selection () +{ + file_list->selection().clear (); + selection.clear (); +} + +void +SoundFileBrowser::dir_list_selected(gint row, gint col, GdkEvent* ev) +{ + current_member = ""; + current_group = ""; + + group_selected(); /* EMIT_SIGNAL */ +} + +void +SoundFileBrowser::file_list_selected(gint row, gint col, GdkEvent* ev) +{ + current_group = ""; + current_member = fs_selector.get_filename(); + + selection.push_back (RowTaggedString (row, current_member)); + + member_selected(safety_check_file(current_member)); /* EMIT_SIGNAL */ +} + +void +SoundFileBrowser::file_list_deselected(gint row, gint col, GdkEvent* ev) +{ + current_group = ""; + current_member = file_list->cell (row, 0).get_text(); + + for (list::iterator i = selection.begin(); i != selection.end(); ++i) { + if ((*i).row == row) { + selection.erase (i); + break; + } + } + + member_deselected(); /* EMIT_SIGNAL */ +} + +string +SoundFileBrowser::safety_check_file(string file) +{ + if (file.rfind(".wav") == string::npos && + file.rfind(".aiff")== string::npos && + file.rfind(".aif") == string::npos && + file.rfind(".snd") == string::npos && + file.rfind(".au") == string::npos && + file.rfind(".raw") == string::npos && + file.rfind(".sf") == string::npos && + file.rfind(".cdr") == string::npos && + file.rfind(".smp") == string::npos && + file.rfind(".maud")== string::npos && + file.rfind(".vwe") == string::npos && + file.rfind(".paf") == string::npos && + file.rfind(".voc") == string::npos) { + return ""; + } else { + return file; + } +} + +static int32_t process_node (const char *file, const struct stat *sb, int32_t flag); +static string length2string (const int, const int); + +LibraryTree::LibraryTree () + : Gtk::VBox(false, 3), + btn_box_top(true, 4), + btn_box_bottom (true, 4), + add_btn(_("Add to Library...")), + remove_btn(_("Remove...")), + find_btn(_("Find...")), + folder_btn(_("Add Folder")), + files_select(_("Add audio file or directory")) +{ + set_border_width (3); + + pack_start(hbox, true, true); + pack_start(btn_box_top, false, false); + pack_start(btn_box_bottom, false, false); + + hbox.pack_start(scroll); + scroll.set_usize (200, 150); + scroll.set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + scroll.add_with_viewport(tree); + tree.set_selection_mode(GTK_SELECTION_MULTIPLE); + + btn_box_top.pack_start(add_btn); + btn_box_top.pack_start(folder_btn); + btn_box_top.pack_start(remove_btn); + + btn_box_bottom.pack_start(find_btn); + + remove_btn.set_sensitive (false); + + add_btn.clicked.connect (slot (*this, &LibraryTree::add_btn_clicked)); + folder_btn.clicked.connect (slot(*this, &LibraryTree::folder_btn_clicked)); + remove_btn.clicked.connect (slot(*this, &LibraryTree::remove_btn_clicked)); + find_btn.clicked.connect (slot (*this, &LibraryTree::find_btn_clicked)); + + files_select.hide_fileop_buttons(); + files_select.set_filename("/"); + files_select.get_ok_button()->clicked.connect (slot ( *this, + &LibraryTree::file_ok_clicked)); + files_select.get_cancel_button()->clicked.connect (slot ( *this, + &LibraryTree::file_cancel_clicked)); + + + Library->added_group.connect (slot (*this, &LibraryTree::added_group)); + Library->removed_group.connect (slot (*this, &LibraryTree::removed_group)); + Library->added_member.connect (slot (*this, &LibraryTree::added_member)); + Library->removed_member.connect (slot (*this, &LibraryTree::removed_member)); + + current_group = ""; + current_member = ""; + + populate (); +} + +LibraryTree::~LibraryTree () +{ +} + +void +LibraryTree::clear_selection () +{ + using namespace Gtk::Tree_Helpers; + for (SelectionList::iterator i = tree.selection().begin(); i != tree.selection().end(); ++i) { + (*i)->deselect (); + } + selection.clear (); +} + +void +LibraryTree::added_group (string group, string parent) +{ + using namespace Gtk; + ENSURE_GUI_THREAD(bind (slot (*this, &LibraryTree::added_group), group, parent)); + + Tree* parent_tree; + if (parent.length()) { + parent_tree = uri_mapping[parent]->get_subtree(); + } else { + parent_tree = &tree; + } + + TreeItem *item = manage(new TreeItem(Library->get_label(group))); + Tree_Helpers::ItemList items = parent_tree->tree(); + Tree_Helpers::ItemList::iterator i = items.begin(); + + list groups; + Library->get_groups(groups, parent); + list::iterator j = groups.begin(); + + while (i != items.end() && j != groups.end()){ + if ((cmp_nocase(Library->get_label(group),Library->get_label(*j)) <= 0) || + !((*i)->get_subtree())){ + + break; + } + ++i; + ++j; + } + + parent_tree->tree().insert (i, *item); + Tree *subtree = manage(new Tree()); + item->set_subtree (*subtree); + item->expand(); + + item->select.connect (bind(slot(*this,&LibraryTree::cb_group_select), item, group)); + + uri_mapping.insert(map::value_type(group, item)); + uri_parent.insert(map::value_type(group, parent)); + + subtree->show(); + item->show(); + + while (gtk_events_pending()){ + gtk_main_iteration(); + } +} + +void +LibraryTree::removed_group (string group) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &LibraryTree::removed_group), group)); + + Gtk::TreeItem* group_item = uri_mapping[group]; + + Gtk::Tree* parent_tree; + if (uri_parent[group].length()) { + parent_tree = uri_mapping[uri_parent[group]]->get_subtree(); + } else { + parent_tree = &tree; + } + + parent_tree->tree().remove(*group_item); + uri_mapping.erase(uri_mapping.find(group)); + uri_parent.erase(uri_parent.find(group)); + + while (gtk_events_pending()){ + gtk_main_iteration(); + } +} + +void +LibraryTree::added_member (string member, string parent) +{ + using namespace Gtk; + + ENSURE_GUI_THREAD(bind (slot (*this, &LibraryTree::added_member), member, parent)); + + Tree* parent_tree; + if (parent.length()) { + parent_tree = uri_mapping[parent]->get_subtree(); + } else { + parent_tree = &tree; + } + + TreeItem *item = manage(new TreeItem(Library->get_label(member))); + Tree_Helpers::ItemList items = parent_tree->tree(); + Tree_Helpers::ItemList::iterator i = items.begin(); + + list members; + Library->get_members(members, parent); + list::iterator j = members.begin(); + + while (i != items.end() && j != members.end()){ + if (cmp_nocase(Library->get_label(member), Library->get_label(*j)) <= 0){ + break; + } + ++i; + ++j; + } + + parent_tree->tree().insert (i, *item); + + item->select.connect + (bind(slot(*this,&LibraryTree::cb_member_select), item, member)); + item->deselect.connect + (bind(slot(*this,&LibraryTree::cb_member_deselect), item, member)); + + uri_mapping.insert(map::value_type(member, item)); + uri_parent.insert(map::value_type(member, parent)); + + item->show(); + + while (gtk_events_pending()){ + gtk_main_iteration(); + } +} + +void +LibraryTree::removed_member (string member) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &LibraryTree::removed_member), member)); + + Gtk::TreeItem* member_item = uri_mapping[member]; + + Gtk::Tree* parent_tree; + if (uri_parent[member].length()) { + parent_tree = uri_mapping[uri_parent[member]]->get_subtree(); + } else { + parent_tree = &tree; + } + + parent_tree->tree().remove(*member_item); + uri_mapping.erase(uri_mapping.find(member)); + uri_parent.erase(uri_parent.find(member)); + + while (gtk_events_pending()){ + gtk_main_iteration(); + } +} + +void +LibraryTree::populate () +{ + subpopulate (&tree, current_group); +} + +void +LibraryTree::subpopulate (Gtk::Tree* tree, string group) +{ + using namespace Gtk; + + list groups; + Library->get_groups(groups, group); + + list::iterator i; + + for (i = groups.begin(); i != groups.end(); ++i) { + TreeItem *item = + manage(new TreeItem(Library->get_label(*i))); + tree->append (*item); + Tree *subtree = manage(new Tree()); + item->set_subtree (*subtree); + + uri_mapping.insert(map::value_type(*i, item)); + uri_parent.insert(map::value_type(*i, group)); + + item->select.connect + (bind(slot(*this,&LibraryTree::cb_group_select), item, *i)); + + subpopulate (subtree, *i); + subtree->show(); + item->expand(); + item->show(); + } + + list members; + Library->get_members(members, group); + for (i = members.begin(); i != members.end(); ++i) { + TreeItem *item = manage(new TreeItem(Library->get_label(*i))); + tree->append (*item); + item->show(); + + uri_mapping.insert(map::value_type(*i, item)); + uri_parent.insert(map::value_type(*i, group)); + + item->select.connect + (bind(slot(*this,&LibraryTree::cb_member_select), item, *i)); + item->deselect.connect + (bind(slot(*this,&LibraryTree::cb_member_deselect), item, *i)); + + } +} + +void +LibraryTree::add_btn_clicked () +{ + files_select.show_all(); +} + +// Gah, too many globals +static string parent_uri; +static vector* old_parent; +static vector* old_parent_uri; + +static void clone_ftw(void*); +static int32_t ftw_return; +static Gtk::ProgressBar* bar; + +void +LibraryTree::file_ok_clicked () +{ + files_select.hide_all(); + + string* file = new string(files_select.get_filename()); + parent_uri = current_group; + + Gtk::Window* progress_win = new Gtk::Window(); + progress_win->set_title(_("Importing")); + progress_win->set_policy(false, false, true); + Gtk::VBox* main_box = manage(new Gtk::VBox()); + progress_win->add(*main_box); + bar = manage(new Gtk::ProgressBar()); + bar->set_activity_mode(true); + bar->set_activity_step(15); + bar->set_activity_blocks(10); + main_box->pack_start(*bar); + Gtk::Button* cancel_btn = manage(new Gtk::Button(_("Cancel"))); + main_box->pack_start(*cancel_btn); + cancel_btn->clicked.connect (slot (*this, &LibraryTree::cancel_import_clicked)); + progress_win->show_all(); + + clone_ftw((void*)file); + + delete progress_win; +} + +void +LibraryTree::cancel_import_clicked() +{ + ftw_return = 1; +} + +void +clone_ftw(void* ptr) +{ + string* file = (string*) ptr; + + old_parent = new vector; + old_parent_uri = new vector; + ftw_return = 0; + + if (ftw (file->c_str(), process_node, 100) < 0){ + warning << compose(_("%1 not added to database"), *file) << endmsg; + } + + delete old_parent; + delete old_parent_uri; + + delete file; +} + +void +LibraryTree::file_cancel_clicked () +{ + files_select.hide_all(); +} + +void +LibraryTree::folder_btn_clicked () +{ + ArdourPrompter prompter (true); + prompter.set_prompt(_("Folder name:")); + + prompter.done.connect(Gtk::Main::quit.slot()); + prompter.show_all(); + + Gtk::Main::run(); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string name; + + prompter.get_result(name); + + if (name.length()) { + Library->add_group(name, current_group); + } + } +} + +void +LibraryTree::cb_group_select (Gtk::TreeItem* item, string uri) +{ + current_group = uri; + current_member = ""; + remove_btn.set_sensitive(true); + + group_selected(); /* EMIT_SIGNAL */ +} + +void +LibraryTree::cb_member_select (Gtk::TreeItem* item, string uri) +{ + current_member = uri; + current_group = ""; + selection.push_back (uri); + member_selected(uri); /* EMIT_SIGNAL */ + remove_btn.set_sensitive(true); +} + +void +LibraryTree::cb_member_deselect (Gtk::TreeItem* item, string uri) +{ + current_member = ""; + current_group = ""; + selection.remove (uri); + + member_deselected(); /* EMIT_SIGNAL */ +} + +void +LibraryTree::find_btn_clicked () +{ + SearchSounds* search = new SearchSounds (); + + search->file_chosen.connect(slot (*this, &LibraryTree::file_found)); + search->show_all(); +} + +void +LibraryTree::file_found (string uri, bool multi) +{ + file_chosen (Library->get_member_filename(uri), multi); /* EMIT_SIGNAL */ +} + +void +LibraryTree::remove_btn_clicked () +{ + if (current_member != ""){ + Library->remove_member(current_member); + } else if (current_group != ""){ + Library->remove_group(current_group); + } else { + error << _("Should not be reached") << endmsg; + } + + current_member = ""; + current_group = ""; + + remove_btn.set_sensitive(false); + + deselected(); /* EMIT_SIGNAL */ +} + +string +length2string (const int32_t frames, const int32_t sample_rate) +{ + int secs = (int) (frames / (float) sample_rate); + int hrs = secs / 3600; + secs -= (hrs * 3600); + int mins = secs / 60; + secs -= (mins * 60); + + int total_secs = (hrs * 3600) + (mins * 60) + secs; + int frames_remaining = frames - (total_secs * sample_rate); + float fractional_secs = (float) frames_remaining / sample_rate; + + char duration_str[32]; + sprintf (duration_str, "%02d:%02d:%05.2f", hrs, mins, (float) secs + fractional_secs); + + return duration_str; +} + +int +process_node (const char *file, const struct stat *sb, int32_t flag) +{ + bar->set_value(0.0); + while (gtk_events_pending()){ + gtk_main_iteration(); + } + bar->set_value(1.0); + + string s_file(file); + + if (s_file.find("/.") != string::npos){ + return ftw_return; + } + + if (flag == FTW_D) { + string::size_type size = s_file.find_last_of('/'); + string label = s_file.substr(++size); + + while (!old_parent->empty() + && (s_file.find(old_parent->back()) == string::npos)) { + + parent_uri = old_parent_uri->back(); + old_parent_uri->pop_back(); + old_parent->pop_back(); + } + + string uri = Library->add_group(label, parent_uri); + + old_parent->push_back(s_file); + old_parent_uri->push_back(parent_uri); + parent_uri = uri; + + return ftw_return; + } else if (flag != FTW_F) { + return ftw_return; + } + + // We can't realistically check every file - or can we ? + char* suffix; + if ((suffix = strrchr (file, '.')) == 0) { + return ftw_return; + } + + if (*(suffix+1) == '\0') { + return ftw_return; + } + + if (strcasecmp (suffix+1, "wav") != 0 && + strcasecmp (suffix+1, "aiff") != 0 && + strcasecmp (suffix+1, "aif") != 0 && + strcasecmp (suffix+1, "snd") != 0 && + strcasecmp (suffix+1, "au") != 0 && + strcasecmp (suffix+1, "raw") != 0 && + strcasecmp (suffix+1, "sf") != 0 && + strcasecmp (suffix+1, "cdr") != 0 && + strcasecmp (suffix+1, "smp") != 0 && + strcasecmp (suffix+1, "maud") != 0 && + strcasecmp (suffix+1, "vwe") != 0 && + strcasecmp (suffix+1, "paf") != 0 && + strcasecmp (suffix+1, "voc") != 0) { + + return ftw_return; + } + + /* OK, it stands a good chance of being a sound file that we + might be able to handle. + */ + + SNDFILE *sf; + SF_INFO info; + if ((sf = sf_open ((char *) file, SFM_READ, &info)) < 0) { + error << compose(_("file \"%1\" could not be opened"), file) << endmsg; + return ftw_return; + } + sf_close (sf); + + string uri = Library->add_member(file, parent_uri); + + Library->set_field(uri, "channels", compose("%1", info.channels)); + Library->set_field(uri, "samplerate", compose("%1", info.samplerate)); + Library->set_field(uri, "resolution", compose("%1", sndfile_data_width(info.format))); + Library->set_field(uri, "format", compose("%1", info.format)); + + return ftw_return; +} + +static const gchar* selector_titles[] = { + N_("Field"), + N_("Value"), + 0 +}; + +SoundFileBox::SoundFileBox (string uri, bool meta) + : + uri(uri), + metadata(meta), + sf_info(new SF_INFO), + current_pid(0), + fields(_fields_refiller, this, internationalize (selector_titles), + false, true), + main_box (false, 3), + top_box (true, 4), + bottom_box (true, 4), + play_btn(_("Play")), + stop_btn(_("Stop")), + add_field_btn(_("Add Field...")), + remove_field_btn(_("Remove Field")) +{ + set_name ("SoundFileBox"); + + border_frame.set_label (_("Soundfile Info")); + border_frame.add (main_box); + + pack_start (border_frame); + set_border_width (4); + + Gtk::HBox* path_box = manage (new HBox); + + path_box->set_spacing (4); + path_box->pack_start (path, false, false); + path_box->pack_start (path_entry, true, true); + + main_box.set_border_width (4); + + main_box.pack_start(label, false, false); + main_box.pack_start(*path_box, false, false); + main_box.pack_start(length, false, false); + main_box.pack_start(format, false, false); + main_box.pack_start(channels, false, false); + main_box.pack_start(samplerate, false, false); + if (metadata){ + main_box.pack_start(fields, true, true); + main_box.pack_start(top_box, false, false); + } + main_box.pack_start(bottom_box, false, false); + + fields.set_usize(200, 150); + + top_box.set_homogeneous(true); + top_box.pack_start(add_field_btn); + top_box.pack_start(remove_field_btn); + + remove_field_btn.set_sensitive(false); + + bottom_box.set_homogeneous(true); + bottom_box.pack_start(play_btn); + bottom_box.pack_start(stop_btn); + + play_btn.clicked.connect (slot (*this, &SoundFileBox::play_btn_clicked)); + stop_btn.clicked.connect (slot (*this, &SoundFileBox::stop_btn_clicked)); + + PublicEditor& edit = ARDOUR_UI::instance()->the_editor(); + ARDOUR::Session* sess = edit.current_session(); + if (!sess) { + play_btn.set_sensitive(false); + } else { + sess->AuditionActive.connect(slot (*this, &SoundFileBox::audition_status_changed)); + } + + add_field_btn.clicked.connect + (slot (*this, &SoundFileBox::add_field_clicked)); + remove_field_btn.clicked.connect + (slot (*this, &SoundFileBox::remove_field_clicked)); + + fields.selection_made.connect (slot (*this, &SoundFileBox::field_selected)); + fields.choice_made.connect (slot (*this, &SoundFileBox::field_chosen)); + + Library->fields_changed.connect (slot (*this, &SoundFileBox::setup_fields)); + + if (setup_labels (uri)) { + throw failed_constructor(); + } + + show_all(); + stop_btn.hide(); +} + +SoundFileBox::~SoundFileBox () +{ +} + +void +SoundFileBox::_fields_refiller (Gtk::CList &list, void* arg) +{ + ((SoundFileBox *) arg)->fields_refiller (list); +} + +void +SoundFileBox::fields_refiller (Gtk::CList &clist) +{ + if (metadata) { + list flist; + Library->get_fields(flist); + list::iterator i; + + const gchar *rowdata[3]; + guint row = 0; + for (i=flist.begin(); i != flist.end(); ++i, ++row){ + if (*i != "channels" && *i != "samplerate" && + *i != "resolution" && *i != "format") { + + rowdata[0] = (*i).c_str(); + rowdata[1] = Library->get_field(uri, *i).c_str(); + clist.insert_row (row, rowdata); + ++row; + } + } + + clist.column(0).set_auto_resize(true); + clist.set_sort_column (0); + clist.sort (); + } +} + +int +SoundFileBox::setup_labels (string uri) +{ + SNDFILE *sf; + + string file; + if (metadata){ + file = Library->get_member_filename(uri); + } else { + file = uri; + } + + if ((sf = sf_open ((char *) file.c_str(), SFM_READ, sf_info)) < 0) { + error << compose(_("file \"%1\" could not be opened"), file) << endmsg; + return -1; + } + + if (sf_info->frames == 0 && + sf_info->channels == 0 && + sf_info->samplerate == 0 && + sf_info->format == 0 && + sf_info->sections == 0) { + /* .. ok, its not a sound file */ + error << compose(_("file \"%1\" appears not to be an audio file"), file) << endmsg; + return -1; + } + + if (metadata) { + label.set_alignment (0.0f, 0.0f); + label.set_text ("Label: " + Library->get_label(uri)); + } + + path.set_text ("Path: "); + + path_entry.set_text (file); + path_entry.set_position (-1); + + path_entry.focus_in_event.connect (slot (ARDOUR_UI::generic_focus_in_event)); + path_entry.focus_out_event.connect (slot (ARDOUR_UI::generic_focus_out_event)); + + length.set_alignment (0.0f, 0.0f); + length.set_text (compose("Length: %1", length2string(sf_info->frames, sf_info->samplerate))); + + format.set_alignment (0.0f, 0.0f); + format.set_text (compose("Format: %1, %2", + sndfile_major_format(sf_info->format), + sndfile_minor_format(sf_info->format))); + + channels.set_alignment (0.0f, 0.0f); + channels.set_text (compose("Channels: %1", sf_info->channels)); + + samplerate.set_alignment (0.0f, 0.0f); + samplerate.set_text (compose("Samplerate: %1", sf_info->samplerate)); + + return 0; +} + +void +SoundFileBox::play_btn_clicked () +{ + PublicEditor& edit = ARDOUR_UI::instance()->the_editor(); + ARDOUR::Session* sess = edit.current_session(); + if (!sess) { + return; + } + + sess->cancel_audition(); + string file; + + if (metadata) { + file = Library->get_member_filename(uri); + } else { + file = uri; + } + + if (access(file.c_str(), R_OK)) { + warning << compose(_("Could not read file: %1 (%2)."), file, strerror(errno)) << endmsg; + return; + } + + static map region_cache; + + if (region_cache.find (file) == region_cache.end()) { + + AudioRegion::SourceList srclist; + SndFileSource* sfs; + + for (int n=0; n < sf_info->channels; ++n) { + + try { + sfs = new SndFileSource(file+":"+compose("%1", n), false); + srclist.push_back(sfs); + + } catch (failed_constructor& err) { + error << _("Could not access soundfile: ") << file << endmsg; + return; + } + } + + if (srclist.empty()) { + return; + } + + string result; + sess->region_name (result, PBD::basename(srclist[0]->name()), false); + AudioRegion* a_region = new AudioRegion(srclist, 0, srclist[0]->length(), result, 0, Region::DefaultFlags, false); + region_cache[file] = a_region; + } + + play_btn.hide(); + stop_btn.show(); + + sess->audition_region(*region_cache[file]); +} + +void +SoundFileBox::stop_btn_clicked () +{ + PublicEditor& edit = ARDOUR_UI::instance()->the_editor(); + ARDOUR::Session* sess = edit.current_session(); + if (sess) { + sess->cancel_audition(); + play_btn.show(); + stop_btn.hide(); + } +} + +void +SoundFileBox::audition_status_changed (bool active) +{ + if (!active) { + Gtkmmext::UI::instance()->call_slot( slot(*this, &SoundFileBox::stop_btn_clicked)); + } +} + +void +SoundFileBox::add_field_clicked () +{ + ArdourPrompter prompter (true); + prompter.set_prompt(_("Field name:")); + + prompter.show_all(); + prompter.done.connect(Gtk::Main::quit.slot()); + + Gtk::Main::run(); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string name; + + prompter.get_result(name); + + if (name.length()) { + Library->add_field(name); + } + } +} + +void +SoundFileBox::remove_field_clicked () +{ + Library->remove_field(selected_field); + selected_field = ""; + remove_field_btn.set_sensitive(false); +} + +void +SoundFileBox::setup_fields () +{ + ENSURE_GUI_THREAD(slot (*this, &SoundFileBox::setup_fields)); + + fields.rescan(); +} + +void +SoundFileBox::field_chosen (Gtkmmext::Selector *selector, Gtkmmext::SelectionResult *res) +{ + if (res) { + remove_field_btn.set_sensitive(true); + selected_field = selector->clist().row(res->row)[0].get_text(); + } +} + +void +SoundFileBox::field_selected (Gtkmmext::Selector *selector, Gtkmmext::SelectionResult *res) +{ + if (!res){ + return; + } + + string field_name(selector->clist().row(res->row)[0].get_text()); + + ArdourPrompter prompter (true); + prompter.set_prompt(_("Field value:")); + prompter.set_initial_text (selector->clist().row(res->row)[1].get_text()); + + prompter.show_all(); + prompter.done.connect(Gtk::Main::quit.slot()); + + Gtk::Main::run(); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string data; + + prompter.get_result(data); + Library->set_field(uri, field_name, data); + } + + fields.rescan(); +} + +SearchSounds::SearchSounds () + : ArdourDialog ("search sounds dialog"), + find_btn (_("Find")), + and_rbtn (_("AND")), + or_rbtn (_("OR")), + fields(_fields_refiller, this, internationalize(selector_titles)) +{ + set_title (_("ardour: locate soundfiles")); + set_name ("AudioSearchSound"); + + add(main_box); + + or_rbtn.set_group(and_rbtn.group()); + or_rbtn.set_active(true); + rbtn_box.set_homogeneous(true); + rbtn_box.pack_start(and_rbtn); + rbtn_box.pack_start(or_rbtn); + + bottom_box.set_homogeneous(true); + bottom_box.pack_start(find_btn); + + fields.set_usize(200, 150); + + main_box.pack_start(fields); + main_box.pack_start(rbtn_box, false, false); + main_box.pack_start(bottom_box, false, false); + + delete_event.connect (slot (*this, &ArdourDialog::wm_doi_event)); + + find_btn.clicked.connect (slot (*this, &SearchSounds::find_btn_clicked)); + fields.selection_made.connect (slot + (*this, &SearchSounds::field_selected)); + + show_all(); +} + +SearchSounds::~SearchSounds () +{ +} + +void +SearchSounds::_fields_refiller (Gtk::CList &list, void* arg) +{ + ((SearchSounds *) arg)->fields_refiller (list); +} + +void +SearchSounds::fields_refiller (Gtk::CList &clist) +{ + list flist; + Library->get_fields(flist); + list::iterator i; + + const gchar *rowdata[3]; + guint row; + for (row=0,i=flist.begin(); i != flist.end(); ++i, ++row){ + rowdata[0] = (*i).c_str(); + rowdata[1] = ""; + clist.insert_row (row, rowdata); + } + + clist.column(0).set_auto_resize(true); + clist.set_sort_column (0); + clist.sort (); +} + +void +SearchSounds::field_selected (Gtkmmext::Selector *selector, Gtkmmext::SelectionResult *res) +{ + if (!res){ + return; + } + + ArdourPrompter prompter (true); + prompter.set_prompt(_("Field value:")); + + prompter.show_all(); + prompter.done.connect(Gtk::Main::quit.slot()); + + Gtk::Main::run(); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string data; + + prompter.get_result(data); + selector->clist().cell(res->row, 1).set_text(data); + } +} + +void +SearchSounds::find_btn_clicked () +{ + using namespace Gtk::CList_Helpers; + typedef map StringMap; + + StringMap search_info; + + RowList rows = fields.clist().rows(); + RowList::const_iterator i; + + for (i = rows.begin(); i != rows.end(); ++i) { + Cell cfield((*i)[0]); + Cell cdata((*i)[1]); + if (cdata.get_text().length()){ + search_info.insert( + StringMap::value_type(cfield.get_text(), cdata.get_text())); + } + } + + SearchResults* results; + if (and_rbtn.get_active()){ + results = new SearchResults(search_info, true); + } else { + results = new SearchResults(search_info, false); + } + + results->file_chosen.connect (slot (*this, &SearchSounds::file_found)); + results->show_all(); +} + +void +SearchSounds::file_found (string uri, bool multi) +{ + PublicEditor& edit = ARDOUR_UI::instance()->the_editor(); + ARDOUR::Session* sess = edit.current_session(); + if (sess) { + sess->cancel_audition(); + } + + file_chosen (uri, multi); /* EMIT_SIGNAL */ +} + +static const gchar* result_titles[] = { + N_("Results"), + N_("Uris"), + 0 +}; + +SearchResults::SearchResults (map field_values, bool and_search) + : ArdourDialog ("search results dialog"), + search_info(field_values), + search_and (and_search), + selection (""), + main_box (false, 3), + import_box (true, 4), + import_btn (_("Import")), + multichan_check (_("Create multi-channel region")), + results (_results_refiller, this, internationalize (result_titles), false, true) +{ + set_title (_("Ardour: Search Results")); + set_name ("ArdourSearchResults"); + + add(main_box); + set_border_width (3); + + main_box.pack_start(hbox); + hbox.pack_start(results); + + main_box.pack_start(import_box, false, false); + + results.set_usize (200, 150); + + import_box.set_homogeneous(true); + import_box.pack_start(import_btn); + import_box.pack_start(multichan_check); + + import_btn.set_sensitive(false); + multichan_check.set_active(true); + multichan_check.set_sensitive(false); + + delete_event.connect (slot (*this, &ArdourDialog::wm_doi_event)); + + import_btn.clicked.connect (slot (*this, &SearchResults::import_clicked)); + + results.choice_made.connect (slot (*this, &SearchResults::result_chosen)); + + show_all(); +} + +SearchResults::~SearchResults () +{ +} + +void +SearchResults::_results_refiller (Gtk::CList &list, void* arg) +{ + ((SearchResults *) arg)->results_refiller (list); +} + +void +SearchResults::results_refiller (Gtk::CList &clist) +{ + list results; + if (search_and) { + Library->search_members_and (results, search_info); + } else { + Library->search_members_or (results, search_info); + } + + list::iterator i; + const gchar *rowdata[3]; + guint row; + for (row=0, i=results.begin(); i != results.end(); ++i, ++row){ + rowdata[0] = (Library->get_label(*i)).c_str(); + // hide the uri in a hidden column + rowdata[1] = (*i).c_str(); + clist.insert_row (row, rowdata); + } + + clist.column(1).set_visiblity(false); + clist.column(0).set_auto_resize(true); + clist.set_sort_column (0); + clist.sort (); +} + +void +SearchResults::import_clicked () +{ + PublicEditor& edit = ARDOUR_UI::instance()->the_editor(); + ARDOUR::Session* sess = edit.current_session(); + + if (sess) { + sess->cancel_audition(); + } + + file_chosen(selection, multichan_check.get_active()); /* EMIT_SIGNAL */ +} + +void +SearchResults::result_chosen (Gtkmmext::Selector *selector, Gtkmmext::SelectionResult *res) +{ + if (res) { + selection = selector->clist().row(res->row)[1].get_text(); + + if (info_box){ + delete info_box; + info_box = 0; + } + + try { + info_box = new SoundFileBox(selection, true); + } catch (failed_constructor& err) { + /* nothing to do */ + return; + } + + hbox.pack_start(*info_box); + } +} diff --git a/gtk2_ardour/library_ui.h b/gtk2_ardour/library_ui.h new file mode 100644 index 0000000000..ae40aac2d7 --- /dev/null +++ b/gtk2_ardour/library_ui.h @@ -0,0 +1,307 @@ +/* + Copyright (C) 1999-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_library_ui_h__ +#define __ardour_library_ui_h__ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "ardour_dialog.h" + +using std::string; +using std::map; + +struct RowTaggedString { + RowTaggedString (int r, string s) + : row (r), str (s) {} + + int32_t row; + string str; +}; + +class SoundFileBox : public Gtk::VBox +{ + public: + /** + @variable uri is the path name of string. + @variable metadata whether to show the user-added fields from sfdb. + */ + SoundFileBox (string uri, bool metadata); + ~SoundFileBox (); + + SigC::Signal2 file_chosen; + + private: + string uri; + bool metadata; + SF_INFO* sf_info; + + char* playcmd; + pid_t current_pid; + + Gtk::Label label; + Gtk::Label path; + Gtk::Entry path_entry; + Gtk::Label length; + Gtk::Label format; + Gtk::Label channels; + Gtk::Label samplerate; + + Gtkmmext::Selector fields; + string selected_field; + + Gtk::Frame border_frame; + + Gtk::VBox main_box; + Gtk::HBox top_box; + Gtk::HBox bottom_box; + + Gtk::Button play_btn; + Gtk::Button stop_btn; + Gtk::Button add_field_btn; + Gtk::Button remove_field_btn; + + static void _fields_refiller (Gtk::CList &list, void* arg); + void fields_refiller (Gtk::CList &clist); + int setup_labels (string uri); + void setup_fields (); + + void play_btn_clicked (); + void stop_btn_clicked (); + void add_field_clicked (); + void remove_field_clicked (); + + void field_selected (Gtkmmext::Selector *selector, + Gtkmmext::SelectionResult *re); + void field_chosen (Gtkmmext::Selector *selector, + Gtkmmext::SelectionResult *re); + void audition_status_changed (bool state); +}; + +class SearchSounds : public ArdourDialog +{ + public: + SearchSounds (); + ~SearchSounds (); + + SigC::Signal2 file_chosen; + + private: + Gtk::Button find_btn; + + Gtk::RadioButton and_rbtn; + Gtk::RadioButton or_rbtn; + + Gtkmmext::Selector fields; + string selected_field; + + Gtk::VBox main_box; + Gtk::HBox rbtn_box; + Gtk::HBox bottom_box; + + static void _fields_refiller (Gtk::CList &list, void* arg); + void fields_refiller (Gtk::CList &clist); + void setup_fields (); + + void field_selected (Gtkmmext::Selector *selector, + Gtkmmext::SelectionResult *re); + + void find_btn_clicked (); + + void file_found (string uri, bool multi); +}; + +class SearchResults : public ArdourDialog +{ + public: + SearchResults (map field_values, bool and_search); + ~SearchResults (); + + SigC::Signal2 file_chosen; + + private: + map search_info; + bool search_and; + string selection; + + Gtk::VBox main_box; + Gtk::HBox hbox; + Gtk::HBox import_box; + + Gtk::Button import_btn; + Gtk::CheckButton multichan_check; + + SoundFileBox* info_box; + + Gtkmmext::Selector results; + static void _results_refiller (Gtk::CList &list, void* arg); + void results_refiller (Gtk::CList &clist); + + void import_clicked (); + + void result_chosen (Gtkmmext::Selector *selector, + Gtkmmext::SelectionResult *re); +}; + +class LibraryTree : public Gtk::VBox +{ + public: + LibraryTree (); + ~LibraryTree (); + + SigC::Signal2 file_chosen; + SigC::Signal0 group_selected; + SigC::Signal1 member_selected; + SigC::Signal0 member_deselected; + SigC::Signal0 deselected; + + list selection; + void clear_selection (); + + private: + map uri_mapping; + map uri_parent; // this ugly, but necessary + + string current_member; + string current_group; + + Gtk::HBox hbox; + Gtk::VBox framed_box; + Gtk::HBox btn_box_top; + Gtk::HBox btn_box_bottom; + + Gtk::ScrolledWindow scroll; + Gtk::Tree tree; + + Gtk::Button add_btn; + Gtk::Button remove_btn; + Gtk::Button find_btn; + Gtk::Button folder_btn; + + Gtk::FileSelection files_select; + + void file_ok_clicked (); + void file_cancel_clicked (); + + void add_btn_clicked (); + void folder_btn_clicked (); + void remove_btn_clicked (); + void find_btn_clicked (); + + void file_found (string uri, bool multi); + + void cb_group_select (Gtk::TreeItem* item, string uri); + void cb_member_select (Gtk::TreeItem* item, string uri); + void cb_member_deselect (Gtk::TreeItem* item, string uri); + + void populate (); + void subpopulate (Gtk::Tree*, string group); + + void added_group (string, string); + void removed_group (string); + void added_member (string, string); + void removed_member (string); + + void cancel_import_clicked (); +}; + +class SoundFileBrowser : public Gtk::VBox { + public: + SoundFileBrowser (); + ~SoundFileBrowser (); + + SigC::Signal0 group_selected; + SigC::Signal1 member_selected; + SigC::Signal0 member_deselected; + SigC::Signal0 deselected; + + list selection; + void clear_selection (); + + private: + string current_member; + string current_group; + Gtk::FileSelection fs_selector; + Gtk::CList* file_list; + + void dir_list_selected(gint row, gint col, GdkEvent* ev); + void file_list_selected(gint row, gint col, GdkEvent* ev); + void file_list_deselected(gint row, gint col, GdkEvent* ev); + + string safety_check_file(string file); +}; + +class SoundFileSelector : public ArdourDialog { + public: + /** + @variable action the name given to the action button + @variable import is action button sensitive + @variable multi does splitting the region by channel make sense here + @variable persist should this LibraryTree be hidden or deleted when closed + */ + SoundFileSelector (); + ~SoundFileSelector (); + + void run (string action, bool split_makes_sense, bool hide_after_action = false); + void get_result (vector& paths, bool& split); + void hide_import_stuff(); + + SigC::Signal2,bool> Action; + + private: + bool multiable; + bool hide_after_action; + bool sfdb; + + void import_btn_clicked (); + void sfdb_group_selected(); + void browser_group_selected(); + void member_selected(string member, bool sfdb); + void member_deselected(bool sfdb); + void sfdb_deselected(); + void page_switched(Gtk::Notebook_Helpers::Page* page, guint page_num); + + Gtk::HBox main_box; + Gtk::VBox vbox; + Gtk::Notebook notebook; + Gtk::Label sfdb_label; + Gtk::Label fs_label; + + SoundFileBrowser sf_browser; + LibraryTree sfdb_tree; + + Gtk::HBox import_box; + Gtk::Button import_btn; + Gtk::CheckButton split_channels; + Gtk::CheckButton resample_check; + + SoundFileBox* info_box; +}; + +#endif // __ardour_library_ui_h__ diff --git a/gtk2_ardour/location_ui.cc b/gtk2_ardour/location_ui.cc new file mode 100644 index 0000000000..3cac264e50 --- /dev/null +++ b/gtk2_ardour/location_ui.cc @@ -0,0 +1,886 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include +#include + +#include +#include +#include + +#include "ardour_ui.h" +#include "prompter.h" +#include "location_ui.h" +#include "keyboard.h" +#include "utils.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; +using namespace Gtkmmext; + +LocationEditRow::LocationEditRow(Session * sess, Location * loc, int32_t num) + : location(0), session(0), + item_table (1, 7, false), + start_set_button (_("Set")), + start_go_button (_("Go")), + start_clock (X_("LocationEditRowClock"), true), + end_set_button (_("Set")), + end_go_button (_("Go")), + end_clock (X_("LocationEditRowClock"), true), + length_clock (X_("LocationEditRowClock"), true, true), + cd_check_button (_("CD")), + hide_check_button (_("Hidden")), + remove_button (_("Remove")), + scms_check_button (_("SCMS")), + preemph_check_button (_("Pre-Emphasis")) + +{ + + i_am_the_modifier = 0; + + number_label.set_name ("LocationEditNumberLabel"); + name_label.set_name ("LocationEditNameLabel"); + name_entry.set_name ("LocationEditNameEntry"); + start_set_button.set_name ("LocationEditSetButton"); + start_go_button.set_name ("LocationEditGoButton"); + end_set_button.set_name ("LocationEditSetButton"); + end_go_button.set_name ("LocationEditGoButton"); + cd_check_button.set_name ("LocationEditCdButton"); + hide_check_button.set_name ("LocationEditHideButton"); + remove_button.set_name ("LocationEditRemoveButton"); + isrc_label.set_name ("LocationEditNumberLabel"); + isrc_entry.set_name ("LocationEditNameEntry"); + scms_check_button.set_name ("LocationEditCdButton"); + preemph_check_button.set_name ("LocationEditCdButton"); + performer_label.set_name ("LocationEditNumberLabel"); + performer_entry.set_name ("LocationEditNameEntry"); + composer_label.set_name ("LocationEditNumberLabel"); + composer_entry.set_name ("LocationEditNameEntry"); + + + isrc_label.set_text ("ISRC: "); + isrc_label.set_usize (30, -1); + performer_label.set_text ("Performer: "); + performer_label.set_usize (60, -1); + composer_label.set_text ("Composer: "); + composer_label.set_usize (60, -1); + + isrc_entry.set_usize (112, -1); + isrc_entry.set_max_length(12); + isrc_entry.set_editable (true); + + performer_entry.set_usize (100, -1); + performer_entry.set_editable (true); + + composer_entry.set_usize (100, -1); + composer_entry.set_editable (true); + + cd_track_details_hbox.pack_start (isrc_label, false, false); + cd_track_details_hbox.pack_start (isrc_entry, false, false); + cd_track_details_hbox.pack_start (scms_check_button, false, false); + cd_track_details_hbox.pack_start (preemph_check_button, false, false); + cd_track_details_hbox.pack_start (performer_label, false, false); + cd_track_details_hbox.pack_start (performer_entry, true, true); + cd_track_details_hbox.pack_start (composer_label, false, false); + cd_track_details_hbox.pack_start (composer_entry, true, true); + + isrc_entry.changed.connect (slot (*this, &LocationEditRow::isrc_entry_changed)); + isrc_entry.focus_in_event.connect (slot (*this, &LocationEditRow::entry_focus_event)); + isrc_entry.focus_out_event.connect (slot (*this, &LocationEditRow::entry_focus_event)); + + performer_entry.changed.connect (slot (*this, &LocationEditRow::performer_entry_changed)); + performer_entry.focus_in_event.connect (slot (*this, &LocationEditRow::entry_focus_event)); + performer_entry.focus_out_event.connect (slot (*this, &LocationEditRow::entry_focus_event)); + + composer_entry.changed.connect (slot (*this, &LocationEditRow::composer_entry_changed)); + composer_entry.focus_in_event.connect (slot (*this, &LocationEditRow::entry_focus_event)); + composer_entry.focus_out_event.connect (slot (*this, &LocationEditRow::entry_focus_event)); + + scms_check_button.toggled.connect(slot (*this, &LocationEditRow::scms_toggled)); + preemph_check_button.toggled.connect(slot (*this, &LocationEditRow::preemph_toggled)); + + + set_session (sess); + + + item_table.attach (number_label, 0, 1, 0, 1, 0, 0, 3, 0); + + start_hbox.pack_start (start_go_button, false, false); + start_hbox.pack_start (start_clock, false, false); + start_hbox.pack_start (start_set_button, false, false); + + item_table.attach (start_hbox, 2, 3, 0, 1, 0, 0, 4, 0); + + + start_set_button.clicked.connect( bind ( slot (*this, &LocationEditRow::set_button_pressed), LocStart)); + start_go_button.clicked.connect( bind ( slot (*this, &LocationEditRow::go_button_pressed), LocStart)); + start_clock.ValueChanged.connect (bind ( slot (*this, &LocationEditRow::clock_changed), LocStart)); + + + end_hbox.pack_start (end_go_button, false, false); + end_hbox.pack_start (end_clock, false, false); + end_hbox.pack_start (end_set_button, false, false); + + //item_table.attach (end_hbox, 2, 3, 0, 1, 0, 0, 4, 0); + + end_set_button.clicked.connect( bind ( slot (*this, &LocationEditRow::set_button_pressed), LocEnd)); + end_go_button.clicked.connect( bind ( slot (*this, &LocationEditRow::go_button_pressed), LocEnd)); + end_clock.ValueChanged.connect (bind ( slot (*this, &LocationEditRow::clock_changed), LocEnd)); + +// item_table.attach (length_clock, 3, 4, 0, 1, 0, 0, 4, 0); + length_clock.ValueChanged.connect (bind ( slot (*this, &LocationEditRow::clock_changed), LocLength)); + +// item_table.attach (cd_check_button, 4, 5, 0, 1, 0, GTK_FILL, 4, 0); +// item_table.attach (hide_check_button, 5, 6, 0, 1, 0, GTK_FILL, 4, 0); +// item_table.attach (remove_button, 7, 8, 0, 1, 0, GTK_FILL, 4, 0); + + cd_check_button.toggled.connect(slot (*this, &LocationEditRow::cd_toggled)); + hide_check_button.toggled.connect(slot (*this, &LocationEditRow::hide_toggled)); + + remove_button.clicked.connect(slot (*this, &LocationEditRow::remove_button_pressed)); + + pack_start(item_table, true, true); + + set_location (loc); + set_number (num); +} + +LocationEditRow::~LocationEditRow() +{ + if (location) { + start_changed_connection.disconnect(); + end_changed_connection.disconnect(); + name_changed_connection.disconnect(); + changed_connection.disconnect(); + flags_changed_connection.disconnect(); + } +} + +void +LocationEditRow::set_session (Session *sess) +{ + session = sess; + + if (!session) return; + + start_clock.set_session (session); + end_clock.set_session (session); + length_clock.set_session (session); + +} + +void +LocationEditRow::set_number (int num) +{ + number = num; + + if (number >= 0 ) { + number_label.set_text (compose ("%1", number)); + } +} + +void +LocationEditRow::set_location (Location *loc) +{ + if (location) { + start_changed_connection.disconnect(); + end_changed_connection.disconnect(); + name_changed_connection.disconnect(); + changed_connection.disconnect(); + flags_changed_connection.disconnect(); + } + + location = loc; + + if (!location) return; + + if (!hide_check_button.get_parent()) { + item_table.attach (hide_check_button, 6, 7, 0, 1, 0, GTK_FILL, 4, 0); + } + hide_check_button.set_active (location->is_hidden()); + + if (location->is_auto_loop() || location->is_auto_punch()) { + // use label instead of entry + + name_label.set_text (location->name()); + name_label.set_usize (80, -1); + + if (!name_label.get_parent()) { + item_table.attach (name_label, 1, 2, 0, 1, 0, GTK_FILL, 4, 0); + } + + name_label.show(); + + } else { + + name_entry.set_text (location->name()); + name_entry.set_usize (100, -1); + name_entry.set_editable (true); + name_entry.changed.connect (slot (*this, &LocationEditRow::name_entry_changed)); + name_entry.focus_in_event.connect (slot (*this, &LocationEditRow::entry_focus_event)); + name_entry.focus_out_event.connect (slot (*this, &LocationEditRow::entry_focus_event)); + + if (!name_entry.get_parent()) { + item_table.attach (name_entry, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, GTK_FILL, 4, 0); + } + name_entry.show(); + + if (!cd_check_button.get_parent()) { + item_table.attach (cd_check_button, 5, 6, 0, 1, 0, GTK_FILL, 4, 0); + } + if (!remove_button.get_parent()) { + item_table.attach (remove_button, 7, 8, 0, 1, 0, GTK_FILL, 4, 0); + } + + /* XXX i can't find a way to hide the button without messing up + the row spacing, so make it insensitive (paul). + */ + + if (location->is_end()) { + remove_button.set_sensitive (false); + } + + cd_check_button.set_active (location->is_cd_marker()); + cd_check_button.show(); + hide_check_button.show(); + } + + start_clock.set (location->start(), true); + + + if (!location->is_mark()) { + if (!end_hbox.get_parent()) { + item_table.attach (end_hbox, 3, 4, 0, 1, 0, 0, 4, 0); + } + if (!length_clock.get_parent()) { + item_table.attach (length_clock, 4, 5, 0, 1, 0, 0, 4, 0); + } + + end_clock.set (location->end(), true); + length_clock.set (location->length(), true); + + end_set_button.show(); + end_go_button.show(); + end_clock.show(); + length_clock.show(); + } + else { + end_set_button.hide(); + end_go_button.hide(); + end_clock.hide(); + length_clock.hide(); + } + + start_changed_connection = location->start_changed.connect (slot (*this, &LocationEditRow::start_changed)); + end_changed_connection = location->end_changed.connect (slot (*this, &LocationEditRow::end_changed)); + name_changed_connection = location->name_changed.connect (slot (*this, &LocationEditRow::name_changed)); + changed_connection = location->changed.connect (slot (*this, &LocationEditRow::location_changed)); + flags_changed_connection = location->FlagsChanged.connect (slot (*this, &LocationEditRow::flags_changed)); + +} + +gint +LocationEditRow::entry_focus_event (GdkEventFocus* ev) +{ + if (ev->in) { + ARDOUR_UI::instance()->allow_focus (true); + } else { + ARDOUR_UI::instance()->allow_focus (false); + } + return TRUE; +} + + +void +LocationEditRow::name_entry_changed () +{ + ENSURE_GUI_THREAD(slot (*this, &LocationEditRow::name_entry_changed)); + if (i_am_the_modifier || !location) return; + + location->set_name (name_entry.get_text()); +} + + +void +LocationEditRow::isrc_entry_changed () +{ + ENSURE_GUI_THREAD(slot (*this, &LocationEditRow::isrc_entry_changed)); + + if (i_am_the_modifier || !location) return; + + if (isrc_entry.get_text() != "" ) { + + location->cd_info["isrc"] = isrc_entry.get_text(); + + } else { + location->cd_info.erase("isrc"); + } +} + +void +LocationEditRow::performer_entry_changed () +{ + ENSURE_GUI_THREAD(slot (*this, &LocationEditRow::performer_entry_changed)); + + if (i_am_the_modifier || !location) return; + + if (performer_entry.get_text() != "") { + location->cd_info["performer"] = performer_entry.get_text(); + } else { + location->cd_info.erase("performer"); + } +} + +void +LocationEditRow::composer_entry_changed () +{ + ENSURE_GUI_THREAD(slot (*this, &LocationEditRow::composer_entry_changed)); + + if (i_am_the_modifier || !location) return; + + if (composer_entry.get_text() != "") { + location->cd_info["composer"] = composer_entry.get_text(); + } else { + location->cd_info.erase("composer"); + } +} + + +void +LocationEditRow::set_button_pressed (LocationPart part) +{ + if (!location) return; + + switch (part) { + case LocStart: + location->set_start (session->transport_frame ()); + break; + case LocEnd: + location->set_end (session->transport_frame ()); + break; + default: + break; + } +} + +void +LocationEditRow::go_button_pressed (LocationPart part) +{ + if (!location) return; + + switch (part) { + case LocStart: + ARDOUR_UI::instance()->do_transport_locate (location->start()); + break; + case LocEnd: + ARDOUR_UI::instance()->do_transport_locate (location->end()); + break; + default: + break; + } +} + +void +LocationEditRow::clock_changed (LocationPart part) +{ + if (i_am_the_modifier || !location) return; + + switch (part) { + case LocStart: + location->set_start (start_clock.current_time()); + break; + case LocEnd: + location->set_end (end_clock.current_time()); + break; + case LocLength: + location->set_end (location->start() + length_clock.current_duration()); + default: + break; + } + +} + +void +LocationEditRow::cd_toggled () +{ + + if (i_am_the_modifier || !location) return; + location->set_cd (cd_check_button.get_active(), this); + + if (location->is_cd_marker() && !(location->is_mark())) { + + if (location->cd_info.find("isrc") != location->cd_info.end()) { + isrc_entry.set_text(location->cd_info["isrc"]); + } + if (location->cd_info.find("performer") != location->cd_info.end()) { + performer_entry.set_text(location->cd_info["performer"]); + } + if (location->cd_info.find("composer") != location->cd_info.end()) { + composer_entry.set_text(location->cd_info["composer"]); + } + if (location->cd_info.find("scms") != location->cd_info.end()) { + scms_check_button.set_active(true); + } + if (location->cd_info.find("preemph") != location->cd_info.end()) { + preemph_check_button.set_active(true); + } + + if(!cd_track_details_hbox.get_parent()) { + item_table.attach (cd_track_details_hbox, 1, 8, 1, 2, GTK_FILL | GTK_EXPAND, 0, 4, 0); + } + // item_table.resize(2, 7); + cd_track_details_hbox.show_all(); + + } else if (cd_track_details_hbox.get_parent()){ + + item_table.remove (cd_track_details_hbox); + // item_table.resize(1, 7); + redraw_ranges(); /* EMIT_SIGNAL */ + } + +} + + +void +LocationEditRow::hide_toggled () +{ + if (i_am_the_modifier || !location) return; + + location->set_hidden (hide_check_button.get_active(), this); +} + +void +LocationEditRow::remove_button_pressed () +{ + if (!location) return; + + remove_requested(location); /* EMIT_SIGNAL */ +} + + + +void +LocationEditRow::scms_toggled () +{ + if (i_am_the_modifier || !location) return; + + if (scms_check_button.get_active()) { + location->cd_info["scms"] = "on"; + } else { + location->cd_info.erase("scms"); + } + +} + +void +LocationEditRow::preemph_toggled () +{ + if (i_am_the_modifier || !location) return; + + if (preemph_check_button.get_active()) { + location->cd_info["preemph"] = "on"; + } else { + location->cd_info.erase("preemph"); + } +} + +void +LocationEditRow::end_changed (ARDOUR::Location *loc) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &LocationEditRow::end_changed), loc)); + + if (!location) return; + + // update end and length + i_am_the_modifier++; + + end_clock.set (location->end()); + length_clock.set (location->length()); + + i_am_the_modifier--; +} + +void +LocationEditRow::start_changed (ARDOUR::Location *loc) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &LocationEditRow::start_changed), loc)); + + if (!location) return; + + // update end and length + i_am_the_modifier++; + + start_clock.set (location->start()); + + i_am_the_modifier--; +} + +void +LocationEditRow::name_changed (ARDOUR::Location *loc) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &LocationEditRow::name_changed), loc)); + + if (!location) return; + + // update end and length + i_am_the_modifier++; + + name_entry.set_text(location->name()); + name_label.set_text(location->name()); + + i_am_the_modifier--; + +} + +void +LocationEditRow::location_changed (ARDOUR::Location *loc) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &LocationEditRow::location_changed), loc)); + + if (!location) return; + + i_am_the_modifier++; + + start_clock.set (location->start()); + end_clock.set (location->end()); + length_clock.set (location->length()); + + i_am_the_modifier--; + +} + +void +LocationEditRow::flags_changed (ARDOUR::Location *loc, void *src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &LocationEditRow::flags_changed), loc, src)); + + if (!location) return; + + i_am_the_modifier++; + + cd_check_button.set_active (location->is_cd_marker()); + hide_check_button.set_active (location->is_hidden()); + + i_am_the_modifier--; +} + +LocationUI::LocationUI () + : ArdourDialog ("location dialog"), + add_location_button (_("Add New Location")), + add_range_button (_("Add New Range")) +{ + i_am_the_modifier = 0; + + set_title(_("ardour: locations")); + set_wmclass(_("ardour_locations"), "Ardour"); + + set_name ("LocationWindow"); + delete_event.connect (bind (slot (just_hide_it), static_cast(this))); + + add (location_hpacker); + + + location_vpacker.set_border_width (10); + location_vpacker.set_spacing (5); + + + location_vpacker.pack_start (loop_edit_row, false, false); + location_vpacker.pack_start (punch_edit_row, false, false); + + location_rows.set_name("LocationLocRows"); + location_rows_scroller.add_with_viewport (location_rows); + location_rows_scroller.set_name ("LocationLocRowsScroller"); + location_rows_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + location_rows_scroller.set_usize (-1, 130); + + loc_frame_box.set_spacing (5); + loc_frame_box.set_border_width (5); + loc_frame_box.set_name("LocationFrameBox"); + + loc_frame_box.pack_start (location_rows_scroller, true, true); + + add_location_button.set_name ("LocationAddLocationButton"); + loc_frame_box.pack_start (add_location_button, false, false); + + loc_frame.set_name ("LocationLocEditorFrame"); + loc_frame.set_label (_("Location (CD Index) Markers")); + loc_frame.add (loc_frame_box); + loc_range_panes.pack1(loc_frame, true, false); + + + range_rows.set_name("LocationRangeRows"); + range_rows_scroller.add_with_viewport (range_rows); + range_rows_scroller.set_name ("LocationRangeRowsScroller"); + range_rows_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + range_rows_scroller.set_usize (-1, 130); + + range_frame_box.set_spacing (5); + range_frame_box.set_name("LocationFrameBox"); + range_frame_box.set_border_width (5); + range_frame_box.pack_start (range_rows_scroller, true, true); + + add_range_button.set_name ("LocationAddRangeButton"); + range_frame_box.pack_start (add_range_button, false, false); + + range_frame.set_name ("LocationRangeEditorFrame"); + range_frame.set_label (_("Range (CD Track) Markers")); + range_frame.add (range_frame_box); + loc_range_panes.pack2(range_frame, true, false); + location_vpacker.pack_start (loc_range_panes, true, true); + + location_hpacker.pack_start (location_vpacker, true, true); + + add_location_button.clicked.connect (slot (*this, &LocationUI::add_new_location)); + add_range_button.clicked.connect (slot (*this, &LocationUI::add_new_range)); + + //add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_BUTTON_RELEASE_MASK); + + +} + +LocationUI::~LocationUI() +{ +} + + + +gint LocationUI::do_location_remove (ARDOUR::Location *loc) +{ + /* this is handled internally by Locations, but there's + no point saving state etc. when we know the marker + cannot be removed. + */ + + if (loc->is_end()) { + return FALSE; + } + + session->begin_reversible_command (_("remove marker")); + session->add_undo (session->locations()->get_memento()); + session->locations()->remove (loc); + session->add_redo_no_execute (session->locations()->get_memento()); + session->commit_reversible_command (); + + return FALSE; +} + +void LocationUI::location_remove_requested (ARDOUR::Location *loc) +{ + // must do this to prevent problems when destroying + // the effective sender of this event + + Main::idle.connect (bind (slot (*this, &LocationUI::do_location_remove), loc)); +} + + +void LocationUI::location_redraw_ranges () +{ + + range_rows.hide(); + range_rows.show(); + +} + + +void +LocationUI::location_added (Location* location) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &LocationUI::location_added), location)); + + if (location->is_auto_punch()) { + punch_edit_row.set_location(location); + } + else if (location->is_auto_loop()) { + loop_edit_row.set_location(location); + } + else { + refresh_location_list (); + } +} + +void +LocationUI::location_removed (Location* location) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &LocationUI::location_removed), location)); + + if (location->is_auto_punch()) { + punch_edit_row.set_location(0); + } + else if (location->is_auto_loop()) { + loop_edit_row.set_location(0); + } + else { + refresh_location_list (); + } +} + +struct LocationSortByStart { + bool operator() (Location *a, Location *b) { + return a->start() < b->start(); + } +}; + +void +LocationUI::map_locations (Locations::LocationList& locations) +{ + Locations::LocationList::iterator i; + Location* location; + gint n; + int mark_n = 0; + Locations::LocationList temp = locations; + LocationSortByStart cmp; + + temp.sort (cmp); + locations = temp; + + Box_Helpers::BoxList & loc_children = location_rows.children(); + Box_Helpers::BoxList & range_children = range_rows.children(); + LocationEditRow * erow; + + for (n = 0, i = locations.begin(); i != locations.end(); ++n, ++i) { + + location = *i; + + if (location->is_mark()) { + mark_n++; + erow = manage (new LocationEditRow(session, location, mark_n)); + erow->remove_requested.connect (slot (*this, &LocationUI::location_remove_requested)); + erow->redraw_ranges.connect (slot (*this, &LocationUI::location_redraw_ranges)); + loc_children.push_back(Box_Helpers::Element(*erow, false, false, 1)); + } + else if (location->is_auto_punch()) { + punch_edit_row.set_session (session); + punch_edit_row.set_location (location); + } + else if (location->is_auto_loop()) { + loop_edit_row.set_session (session); + loop_edit_row.set_location (location); + } + else { + erow = manage (new LocationEditRow(session, location)); + erow->remove_requested.connect (slot (*this, &LocationUI::location_remove_requested)); + range_children.push_back(Box_Helpers::Element(*erow, false, false, 1)); + } + } + + range_rows.show_all(); + location_rows.show_all(); +} + +void +LocationUI::add_new_location() +{ + if (session) { + jack_nframes_t where = session->audible_frame(); + Location *location = new Location (where, where, "mark", Location::IsMark); + session->begin_reversible_command (_("add marker")); + session->add_undo (session->locations()->get_memento()); + session->locations()->add (location, true); + session->add_redo_no_execute (session->locations()->get_memento()); + session->commit_reversible_command (); + } + +} + +void +LocationUI::add_new_range() +{ + if (session) { + jack_nframes_t where = session->audible_frame(); + Location *location = new Location (where, where, "unnamed"); + session->begin_reversible_command (_("add range marker")); + session->add_undo (session->locations()->get_memento()); + session->locations()->add (location, true); + session->add_redo_no_execute (session->locations()->get_memento()); + session->commit_reversible_command (); + } +} + + +void +LocationUI::refresh_location_list_s (Change ignored) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &LocationUI::refresh_location_list_s), ignored)); + + refresh_location_list (); +} + +void +LocationUI::refresh_location_list () +{ + ENSURE_GUI_THREAD(slot (*this, &LocationUI::refresh_location_list)); + using namespace Box_Helpers; + + BoxList & loc_children = location_rows.children(); + BoxList & range_children = range_rows.children(); + + loc_children.clear(); + range_children.clear(); + + if (session) { + session->locations()->apply (*this, &LocationUI::map_locations); + } + +} + +void +LocationUI::set_session(ARDOUR::Session* sess) +{ + ArdourDialog::set_session (sess); + + if (session) { + session->locations()->changed.connect (slot (*this, &LocationUI::refresh_location_list)); + session->locations()->StateChanged.connect (slot (*this, &LocationUI::refresh_location_list_s)); + session->locations()->added.connect (slot (*this, &LocationUI::location_added)); + session->locations()->removed.connect (slot (*this, &LocationUI::location_removed)); + session->going_away.connect (slot (*this, &LocationUI::session_gone)); + } + refresh_location_list (); +} + +void +LocationUI::session_gone() +{ + ENSURE_GUI_THREAD(slot (*this, &LocationUI::session_gone)); + + hide_all(); + + using namespace Box_Helpers; + BoxList & loc_children = location_rows.children(); + BoxList & range_children = range_rows.children(); + + loc_children.clear(); + range_children.clear(); + + loop_edit_row.set_session (0); + loop_edit_row.set_location (0); + + punch_edit_row.set_session (0); + punch_edit_row.set_location (0); + + ArdourDialog::session_gone(); +} + diff --git a/gtk2_ardour/location_ui.h b/gtk2_ardour/location_ui.h new file mode 100644 index 0000000000..92ea933928 --- /dev/null +++ b/gtk2_ardour/location_ui.h @@ -0,0 +1,198 @@ +/* + Copyright (C) 1999-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_location_ui_h__ +#define __ardour_location_ui_h__ + +#include +#include +#include + +#include "ardour_dialog.h" +#include "keyboard_target.h" + +namespace ARDOUR { + class LocationStack; + class Session; + class Location; +} + +class LocationEditRow : public Gtk::HBox +{ + public: + LocationEditRow (ARDOUR::Session *sess=0, ARDOUR::Location *loc=0, int32_t num=-1); + virtual ~LocationEditRow(); + + void set_location (ARDOUR::Location*); + ARDOUR::Location * get_location() { return location; } + + void set_session (ARDOUR::Session *); + + void set_number (int); + + SigC::Signal1 remove_requested; + SigC::Signal0 redraw_ranges; + + protected: + + enum LocationPart { + LocStart, + LocEnd, + LocLength + }; + + ARDOUR::Location *location; + ARDOUR::Session *session; + + + + Gtk::Table item_table; + + Gtk::Entry name_entry; + Gtk::Label name_label; + Gtk::Label number_label; + + Gtk::HBox start_hbox; + Gtk::Button start_set_button; + Gtk::Button start_go_button; + AudioClock start_clock; + + Gtk::HBox end_hbox; + Gtk::Button end_set_button; + Gtk::Button end_go_button; + AudioClock end_clock; + + AudioClock length_clock; + Gtk::CheckButton cd_check_button; + Gtk::CheckButton hide_check_button; + + Gtk::Button remove_button; + + Gtk::HBox cd_track_details_hbox; + Gtk::Entry isrc_entry; + Gtk::Label isrc_label; + + + Gtk::Label performer_label; + Gtk::Entry performer_entry; + Gtk::Label composer_label; + Gtk::Entry composer_entry; + Gtk::CheckButton scms_check_button; + Gtk::CheckButton preemph_check_button; + + + guint32 i_am_the_modifier; + int number; + + void name_entry_changed (); + void isrc_entry_changed (); + void performer_entry_changed (); + void composer_entry_changed (); + + void set_button_pressed (LocationPart part); + void go_button_pressed (LocationPart part); + + void clock_changed (LocationPart part); + + void cd_toggled (); + void hide_toggled (); + void remove_button_pressed (); + + void scms_toggled (); + void preemph_toggled (); + + gint entry_focus_event (GdkEventFocus* ev); + + void end_changed (ARDOUR::Location *); + void start_changed (ARDOUR::Location *); + void name_changed (ARDOUR::Location *); + void location_changed (ARDOUR::Location *); + void flags_changed (ARDOUR::Location *, void *src); + + SigC::Connection start_changed_connection; + SigC::Connection end_changed_connection; + SigC::Connection name_changed_connection; + SigC::Connection changed_connection; + SigC::Connection flags_changed_connection; + +}; + + +class LocationUI : public ArdourDialog +{ + public: + LocationUI (); + ~LocationUI (); + + void set_session (ARDOUR::Session *); + + private: + + + ARDOUR::LocationStack *locations; + + void session_gone(); + + + Gtk::VBox location_vpacker; + Gtk::HBox location_hpacker; + + LocationEditRow loop_edit_row; + LocationEditRow punch_edit_row; + + Gtk::VPaned loc_range_panes; + + Gtk::Frame loc_frame; + Gtk::VBox loc_frame_box; + Gtk::Button add_location_button; + Gtk::ScrolledWindow location_rows_scroller; + Gtk::VBox location_rows; + + Gtk::Frame range_frame; + Gtk::VBox range_frame_box; + Gtk::Button add_range_button; + Gtk::ScrolledWindow range_rows_scroller; + Gtk::VBox range_rows; + + + /* When any location changes it start + or end points, it sends a signal that is caught + by one of these functions + */ + + void location_remove_requested (ARDOUR::Location *); + + void location_redraw_ranges (); + + gint do_location_remove (ARDOUR::Location *); + + guint32 i_am_the_modifier; + + void add_new_location(); + void add_new_range(); + + void refresh_location_list (); + void refresh_location_list_s (ARDOUR::Change); + void location_removed (ARDOUR::Location *); + void location_added (ARDOUR::Location *); + void map_locations (ARDOUR::Locations::LocationList&); +}; + +#endif // __ardour_location_ui_h__ diff --git a/gtk2_ardour/logmeter.h b/gtk2_ardour/logmeter.h new file mode 100644 index 0000000000..f7ed1dd2be --- /dev/null +++ b/gtk2_ardour/logmeter.h @@ -0,0 +1,49 @@ +#ifndef __ardour_gtk_log_meter_h__ +#define __ardour_gtk_log_meter_h__ + +#if 0 +inline float +_log_meter (float power, double lower_db, double upper_db, double non_linearity) +{ + return (power < lower_db ? 0.0 : pow((power-lower_db)/(upper_db-lower_db), non_linearity)); +} + +inline float +log_meter (float power) +{ + return _log_meter (power, -192.0, 0.0, 8.0); +} +#endif + +inline float +log_meter (float db) +{ + gfloat def = 0.0f; /* Meter deflection %age */ + + if (db < -70.0f) { + def = 0.0f; + } else if (db < -60.0f) { + def = (db + 70.0f) * 0.25f; + } else if (db < -50.0f) { + def = (db + 60.0f) * 0.5f + 2.5f; + } else if (db < -40.0f) { + def = (db + 50.0f) * 0.75f + 7.5f; + } else if (db < -30.0f) { + def = (db + 40.0f) * 1.5f + 15.0f; + } else if (db < -20.0f) { + def = (db + 30.0f) * 2.0f + 30.0f; + } else if (db < 6.0f) { + def = (db + 20.0f) * 2.5f + 50.0f; + } else { + def = 115.0f; + } + + /* 115 is the deflection %age that would be + when db=6.0. this is an arbitrary + endpoint for our scaling. + */ + + return def/115.0f; +} + +#endif /* __ardour_gtk_log_meter_h__ */ diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc new file mode 100644 index 0000000000..88ea54c44c --- /dev/null +++ b/gtk2_ardour/main.cc @@ -0,0 +1,498 @@ +/* + Copyright (C) 2001-2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include "version.h" +#include "ardour_ui.h" +#include "opts.h" + +#include "i18n.h" + +using namespace Gtk; +using namespace GTK_ARDOUR; +using namespace ARDOUR; +using namespace SigC; + +Transmitter error (Transmitter::Error); +Transmitter info (Transmitter::Info); +Transmitter fatal (Transmitter::Fatal); +Transmitter warning (Transmitter::Warning); +TextReceiver text_receiver ("ardour"); + +extern int curvetest (string); + +static ARDOUR_UI *ui = 0; + +static void +shutdown (int status) +{ + char* msg; + + if (status) { + + msg = _("ardour is killing itself for a clean exit\n"); + write (1, msg, strlen (msg)); + /* drastic, but perhaps necessary */ + kill (-getpgrp(), SIGKILL); + /*NOTREACHED*/ + + } else { + + if (ui) { + msg = _("stopping user interface\n"); + write (1, msg, strlen (msg)); + ui->kill(); + } + + pthread_cancel_all (); + } + + exit (status); +} + + +static void +handler (int sig) +{ + char buf[64]; + int n; + + /* XXX its doubtful that snprintf() is async-safe */ + n = snprintf (buf, sizeof(buf), _("%d(%d): received signal %d\n"), getpid(), (int) pthread_self(), sig); + write (1, buf, n); + + shutdown (1); +} + +static void +handler2 (int sig, siginfo_t* ctxt, void* ignored) +{ + handler (sig); +} + +static void * +signal_thread (void *arg) +{ + int sig; + sigset_t blocked; + + PBD::ThreadCreated (pthread_self(), X_("Signal")); + + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); + + /* find out what's blocked right now */ + + //sigprocmask (SIG_SETMASK, 0, &blocked); + if (pthread_sigmask (SIG_SETMASK, 0, &blocked)) { + cerr << "getting blocked signals failed\n"; + } + + /* wait for any of the currently blocked signals. + + According to the man page found in linux 2.6 and 2.4, sigwait() + never returns an error. This is incorrect. Checking the man + pages for some other *nix systems makes it clear that + sigwait() can return several error codes, one of which + is EINTR. This happens if the thread receives a signal + which is not in the blocked set. + + We do not expect that to happen, and if it did we should generally + exit as planned. However, under 2.6, the ptrace facility used + by gdb seems to also cause sigwait() to return with EINTR + but with a signal that sigwait cannot understand. As a result, + "sig" is set to zero, an impossible signal number. + + Handling the EINTR code makes it possible to debug + ardour on a 2.6 kernel. + + */ + + int swerr; + + again: + if ((swerr = sigwait (&blocked, &sig))) { + if (swerr == EINTR) { + goto again; + } else { + cerr << "sigwait failed with " << swerr << endl; + } + } + + cerr << "Signal " << sig << " received\n"; + + if (sig != SIGSEGV) { + + /* unblock signals so we can see them during shutdown. + this will help prod developers not to lose sight + of bugs that cause segfaults etc. during shutdown. + */ + + sigprocmask (SIG_UNBLOCK, &blocked, 0); + } + + shutdown (1); + /*NOTREACHED*/ + return 0; +} + +int +catch_signals (void) +{ + struct sigaction action; + pthread_t signal_thread_id; + sigset_t signals; + +// if (setpgid (0,0)) { + if (setsid ()) { + warning << compose (_("cannot become new process group leader (%1)"), + strerror (errno)) + << endmsg; + } + + sigemptyset (&signals); + sigaddset(&signals, SIGHUP); + sigaddset(&signals, SIGINT); + sigaddset(&signals, SIGQUIT); + sigaddset(&signals, SIGPIPE); + sigaddset(&signals, SIGTERM); + sigaddset(&signals, SIGUSR1); + sigaddset(&signals, SIGUSR2); + + + /* install a handler because otherwise + pthreads behaviour is undefined when we enter + sigwait. + */ + + action.sa_handler = handler; + action.sa_mask = signals; + action.sa_flags = SA_RESTART|SA_RESETHAND; + + for (int i = 1; i < 32; i++) { + if (sigismember (&signals, i)) { + if (sigaction (i, &action, 0)) { + cerr << compose (_("cannot setup signal handling for %1"), i) << endl; + return -1; + } + } + } + + /* this sets the signal mask for this and all + subsequent threads that do not reset it. + */ + + if (pthread_sigmask (SIG_SETMASK, &signals, 0)) { + cerr << compose (_("cannot set default signal mask (%1)"), strerror (errno)) << endl; + return -1; + } + + /* start a thread to wait for signals */ + + if (pthread_create_and_store ("signal", &signal_thread_id, 0, signal_thread, 0)) { + cerr << "cannot create signal catching thread" << endl; + return -1; + } + + pthread_detach (signal_thread_id); + return 0; +} + +string +which_ui_rcfile () +{ + string rcfile; + char* envvar; + + if ((envvar = getenv("ARDOUR_UI_RC")) == 0) { + rcfile = find_config_file ("ardour_ui.rc"); + + if (rcfile.length() == 0) { + warning << _("Without a UI style file, ardour will look strange.\n Please set ARDOUR_UI_RC to point to a valid UI style file") << endmsg; + } + } else { + rcfile = envvar; + } + + return rcfile; +} + +gint +show_ui_callback (void *arg) +{ + ARDOUR_UI * ui = (ARDOUR_UI *) arg; + + ui->hide_splash(); + ui->show (); + + return FALSE; +} + +gint +jack_fooey (GdkEventAny* ignored) +{ + Main::quit (); + return FALSE; +} + +void +jack_foobar () +{ + Main::quit (); +} + +void +gui_jack_error () +{ + Window win (GTK_WINDOW_DIALOG); + VBox vpacker; + Button ok (_("OK")); + Label label (_("Ardour could not connect to JACK.\n\ +There are several possible reasons:\n\ +\n\ +1) JACK is not running.\n\ +2) JACK is running as another user, perhaps root.\n\ +3) There is already another client called \"ardour\".\n\ +\n\ +Please consider the possibilities, and perhaps (re)start JACK.")); + + vpacker.set_spacing (12); + vpacker.pack_start (label); + vpacker.pack_start (ok, false, false); + + win.set_title (_("ardour: unplugged")); + win.set_border_width (7); + win.add (vpacker); + win.show_all (); + win.delete_event.connect (SigC::slot (jack_fooey)); + win.add_events (GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_PRESS_MASK); + win.set_position (GTK_WIN_POS_CENTER); + win.realize (); + win.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + + ok.clicked.connect (SigC::slot (jack_foobar)); + + ok.grab_focus (); + + Main::run (); +} + +int +main (int argc, char *argv[]) +{ + ARDOUR::AudioEngine *engine; + char *null_file_list[] = { 0 }; + + gtk_set_locale (); + + (void) bindtextdomain (PACKAGE, LOCALEDIR); + (void) textdomain (PACKAGE); + + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); + + catch_signals (); + + text_receiver.listen_to (error); + text_receiver.listen_to (info); + text_receiver.listen_to (fatal); + text_receiver.listen_to (warning); + + + if (parse_opts (argc, argv)) { + exit (1); + } + + if (curvetest_file) { + return curvetest (curvetest_file); + } + + /* desktop standard themes: just say no! */ + + if (getenv("GTK_RC_FILES")) { + unsetenv("GTK_RC_FILES"); + } + + if (getenv("GTK2_RC_FILES")) { + unsetenv("GTK_RC_FILES"); + } + + gtk_rc_set_default_files (null_file_list); + + cout << _("Ardour/GTK ") + << VERSIONSTRING + << _("\n (built using ") + << gtk_ardour_major_version << '.' + << gtk_ardour_minor_version << '.' + << gtk_ardour_micro_version + << _(" with libardour ") + << libardour_major_version << '.' + << libardour_minor_version << '.' + << libardour_micro_version +#ifdef __GNUC__ + << _(" and GCC version ") << __VERSION__ +#endif + << ')' + << endl; + + if (just_version) { + exit (0); + } + + if (no_splash) { + cerr << _("Copyright (C) 1999-2005 Paul Davis") << endl + << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl + << endl + << _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl + << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl + << _("This is free software, and you are welcome to redistribute it ") << endl + << _("under certain conditions; see the source for copying conditions.") + << endl; + } + + try { + ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile()); + } + + catch (failed_constructor& err) { + error << _("could not create ARDOUR GUI") << endmsg; + exit (1); + } + + + if (!no_splash) { + ui->show_splash (); + if (session_name.length()) { + gtk_timeout_add (4000, show_ui_callback, ui); + } + } + + try { + engine = new ARDOUR::AudioEngine (jack_client_name); + ARDOUR::init (*engine, use_vst, try_hw_optimization, handler2); + ui->set_engine (*engine); + } + + catch (AudioEngine::NoBackendAvailable& err) { + gui_jack_error (); + error << compose (_("Could not connect to JACK server as \"%1\""), jack_client_name) << endmsg; + return -1; + } + + catch (failed_constructor& err) { + error << _("could not initialize Ardour.") << endmsg; + exit (1); + } + + /* load session, if given */ + string name, path; + + if (session_name.length()){ + bool isnew; + + if (Session::find_session (session_name, path, name, isnew)) { + error << compose(_("could not load command line session \"%1\""), session_name) << endmsg; + } else { + + if (new_session) { + + /* command line required that the session be new */ + + if (isnew) { + + /* popup the new session dialog + once everything else is OK. + */ + + Main::idle.connect (bind (slot (*ui, &ARDOUR_UI::cmdline_new_session), path)); + ui->set_will_create_new_session_automatically (true); + + } else { + + /* it wasn't new, but we require a new session */ + + error << compose (_("\n\nA session named \"%1\" already exists.\n\ +To avoid this message, start ardour as \"ardour %1"), path) + << endmsg; + goto out; + } + + } else { + + /* command line didn't require a new session */ + + if (isnew) { + error << compose (_("\n\nNo session named \"%1\" exists.\n\ +To create it from the command line, start ardour as \"ardour --new %1"), path) + << endmsg; + goto out; + } + + ui->load_session (path, name); + } + } + + if (no_splash) { + ui->show(); + } + + } else { + ui->hide_splash (); + ui->show (); + if (!Config->get_no_new_session_dialog()) { + ui->new_session (true); + } + } + + ui->run (text_receiver); + + delete ui; + ui = 0; + + out: + delete engine; + ARDOUR::cleanup (); + shutdown (0); +} + diff --git a/gtk2_ardour/marker.cc b/gtk2_ardour/marker.cc new file mode 100644 index 0000000000..0014476c29 --- /dev/null +++ b/gtk2_ardour/marker.cc @@ -0,0 +1,449 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include "marker.h" +#include "public_editor.h" +#include "canvas-simpleline.h" +#include "utils.h" + +#include "i18n.h" + +Marker::Marker (PublicEditor& ed, GtkCanvasGroup *parent, guint32 rgba, const string& annotation, + Type type, gint (*callback)(GtkCanvasItem *, GdkEvent *, gpointer), jack_nframes_t frame) + + : editor (ed), _type(type) +{ + double label_offset = 0; + + /* Shapes we use: + + Mark: + + (0,0) -> (6,0) + ^ | + | V + (0,5) (6,5) + \ / + (3,10) + + + TempoMark: + MeterMark: + + (3,0) + / \ + (0,5) -> (6,5) + ^ | + | V + (0,10)<-(6,10) + + + Start: + + 0,0 -> 5,0 + | \ + | 10,5 + | / + 0,10 -> 5,10 + + End: + + 5,0 -> 10,0 + / | + 0,5 | + \ | + 5,10 <-10,10 + + + TransportStart: + + 0,0->3,0 + | | + | | + | | + | 3,8 -> 7,8 + | | + 0,11 ------ 7,11 + + TransportEnd: + + 4,0->7,0 + | | + | | + | | + 0,8 ---- 4,8 | + | | + 0,11 -------- 7,11 + + + PunchIn: + + 0,0 ------> 8,0 + | / + | / + | 4,5 + | | + | | + | | + 0,11->4,11 + + PunchOut + + 0,0 -->-8,0 + \ | + \ | + 4,5 | + | | + | | + | | + 4,11->8,11 + + + */ + + switch (type) { + case Mark: + points = gtk_canvas_points_new (6); + + points->coords[0] = 0.0; + points->coords[1] = 0.0; + + points->coords[2] = 6.0; + points->coords[3] = 0.0; + + points->coords[4] = 6.0; + points->coords[5] = 5.0; + + points->coords[6] = 3.0; + points->coords[7] = 10.0; + + points->coords[8] = 0.0; + points->coords[9] = 5.0; + + points->coords[10] = 0.0; + points->coords[11] = 0.0; + + shift = 3; + label_offset = 8.0; + break; + + case Tempo: + case Meter: + points = gtk_canvas_points_new (6); + + points->coords[0] = 3.0; + points->coords[1] = 0.0; + + points->coords[2] = 6.0; + points->coords[3] = 5.0; + + points->coords[4] = 6.0; + points->coords[5] = 10.0; + + points->coords[6] = 0.0; + points->coords[7] = 10.0; + + points->coords[8] = 0.0; + points->coords[9] = 5.0; + + points->coords[10] = 3.0; + points->coords[11] = 0.0; + + shift = 3; + label_offset = 8.0; + break; + + case Start: + points = gtk_canvas_points_new (6); + + points->coords[0] = 0.0; + points->coords[1] = 0.0; + + points->coords[2] = 5.0; + points->coords[3] = 0.0; + + points->coords[4] = 10.0; + points->coords[5] = 5.0; + + points->coords[6] = 5.0; + points->coords[7] = 10.0; + + points->coords[8] = 0.0; + points->coords[9] = 10.0; + + points->coords[10] = 0.0; + points->coords[11] = 0.0; + + shift = 10; + label_offset = 12.0; + break; + + case End: + points = gtk_canvas_points_new (6); + + points->coords[0] = 5.0; + points->coords[1] = 0.0; + + points->coords[2] = 10.0; + points->coords[3] = 0.0; + + points->coords[4] = 10.0; + points->coords[5] = 10.0; + + points->coords[6] = 5.0; + points->coords[7] = 10.0; + + points->coords[8] = 0.0; + points->coords[9] = 5.0; + + points->coords[10] = 5.0; + points->coords[11] = 0.0; + + shift = 0; + label_offset = 12.0; + break; + + case LoopStart: + points = gtk_canvas_points_new (7); + + points->coords[0] = 0.0; + points->coords[1] = 0.0; + + points->coords[2] = 4.0; + points->coords[3] = 0.0; + + points->coords[4] = 4.0; + points->coords[5] = 8.0; + + points->coords[6] = 8.0; + points->coords[7] = 8.0; + + points->coords[8] = 8.0; + points->coords[9] = 11.0; + + points->coords[10] = 0.0; + points->coords[11] = 11.0; + + points->coords[12] = 0.0; + points->coords[13] = 0.0; + + shift = 0; + label_offset = 11.0; + break; + + case LoopEnd: + points = gtk_canvas_points_new (7); + + points->coords[0] = 8.0; + points->coords[1] = 0.0; + + points->coords[2] = 8.0; + points->coords[3] = 11.0; + + points->coords[4] = 0.0; + points->coords[5] = 11.0; + + points->coords[6] = 0.0; + points->coords[7] = 8.0; + + points->coords[8] = 4.0; + points->coords[9] = 8.0; + + points->coords[10] = 4.0; + points->coords[11] = 0.0; + + points->coords[12] = 8.0; + points->coords[13] = 0.0; + + shift = 8; + label_offset = 11.0; + break; + + case PunchIn: + points = gtk_canvas_points_new (6); + + points->coords[0] = 0.0; + points->coords[1] = 0.0; + + points->coords[2] = 8.0; + points->coords[3] = 0.0; + + points->coords[4] = 4.0; + points->coords[5] = 4.0; + + points->coords[6] = 4.0; + points->coords[7] = 11.0; + + points->coords[8] = 0.0; + points->coords[9] = 11.0; + + points->coords[10] = 0.0; + points->coords[11] = 0.0; + + shift = 0; + label_offset = 10.0; + break; + + case PunchOut: + points = gtk_canvas_points_new (6); + + points->coords[0] = 0.0; + points->coords[1] = 0.0; + + points->coords[2] = 8.0; + points->coords[3] = 0.0; + + points->coords[4] = 8.0; + points->coords[5] = 11.0; + + points->coords[6] = 4.0; + points->coords[7] = 11.0; + + points->coords[8] = 4.0; + points->coords[9] = 4.0; + + points->coords[10] = 0.0; + points->coords[11] = 0.0; + + shift = 8; + label_offset = 11.0; + break; + + } + + frame_position = frame; + unit_position = editor.frame_to_unit (frame); + + /* adjust to properly locate the tip */ + + unit_position -= shift; + + group = gtk_canvas_item_new (parent, + gtk_canvas_group_get_type(), + "x", unit_position, + "y", 1.0, + NULL); + + // cerr << "set mark al points, nc = " << points->num_points << endl; + mark = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_polygon_get_type(), + "points", points, + "fill_color_rgba", rgba, + "outline_color", "black", + NULL); + + string fontname = get_font_for_style (N_("MarkerText")); + + text = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_text_get_type (), + "text", annotation.c_str(), + "x", label_offset, + "y", 0.0, + "font", fontname.c_str(), + "anchor", GTK_ANCHOR_NW, + "fill_color", "black", + NULL); + + gtk_object_set_data (GTK_OBJECT(group), "marker", this); + gtk_signal_connect (GTK_OBJECT(group), "event", (GtkSignalFunc) callback, &editor); + + editor.ZoomChanged.connect (slot (*this, &Marker::reposition)); +} + +Marker::~Marker () +{ + /* destroying the group destroys its contents */ + gtk_object_destroy (GTK_OBJECT(group)); + gtk_canvas_points_unref (points); +} + +void +Marker::set_name (const string& name) +{ + gtk_canvas_item_set (text, "text", name.c_str(), NULL); +} + +void +Marker::set_position (jack_nframes_t frame) +{ + double new_unit_position = editor.frame_to_unit (frame); + new_unit_position -= shift; + gtk_canvas_item_move (group, new_unit_position - unit_position, 0.0); + frame_position = frame; + unit_position = new_unit_position; +} + +void +Marker::reposition () +{ + set_position (frame_position); +} + +void +Marker::show () +{ + gtk_canvas_item_show (group); +} + +void +Marker::hide () +{ + gtk_canvas_item_hide (group); +} + +void +Marker::set_color_rgba (uint32_t color) +{ + gtk_canvas_item_set (mark, "fill_color_rgba", color, NULL); +} + +/***********************************************************************/ + +TempoMarker::TempoMarker (PublicEditor& editor, GtkCanvasGroup *parent, guint32 rgba, const string& text, + ARDOUR::TempoSection& temp, + gint (*callback)(GtkCanvasItem *, GdkEvent *, gpointer)) + : Marker (editor, parent, rgba, text, Tempo, callback, 0), + _tempo (temp) +{ + set_position (_tempo.frame()); + gtk_object_set_data (GTK_OBJECT(group), "tempo_marker", this); +} + +TempoMarker::~TempoMarker () +{ +} + +/***********************************************************************/ + +MeterMarker::MeterMarker (PublicEditor& editor, GtkCanvasGroup *parent, guint32 rgba, const string& text, + ARDOUR::MeterSection& m, + gint (*callback)(GtkCanvasItem *, GdkEvent *, gpointer)) + : Marker (editor, parent, rgba, text, Meter, callback, 0), + _meter (m) +{ + set_position (_meter.frame()); + gtk_object_set_data (GTK_OBJECT(group), "meter_marker", this); +} + +MeterMarker::~MeterMarker () +{ +} diff --git a/gtk2_ardour/marker.h b/gtk2_ardour/marker.h new file mode 100644 index 0000000000..01f1404a82 --- /dev/null +++ b/gtk2_ardour/marker.h @@ -0,0 +1,107 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __gtk_ardour_marker_h__ +#define __gtk_ardour_marker_h__ + +#include +#include +#include +#include +#include + +namespace ARDOUR { + class TempoSection; + class MeterSection; +} + +class PublicEditor; + +class Marker : public SigC::Object +{ + public: + enum Type { + Mark, + Tempo, + Meter, + Start, + End, + LoopStart, + LoopEnd, + PunchIn, + PunchOut + }; + + Marker (PublicEditor& editor, GtkCanvasGroup *parent, guint32 rgba, const string& text, Type, + gint (*callback)(GtkCanvasItem *, GdkEvent *, gpointer), jack_nframes_t frame = 0); + virtual ~Marker (); + + void set_position (jack_nframes_t); + void set_name (const string&); + void set_color_rgba (uint32_t rgba); + + void hide (); + void show (); + + Type type () { return _type; } + + protected: + PublicEditor& editor; + + GtkCanvasItem *group; + GtkCanvasItem *mark; + GtkCanvasItem *text; + GtkCanvasPoints *points; + + double unit_position; + jack_nframes_t frame_position; + unsigned char shift; /* should be double, but its always small and integral */ + Type _type; + + void reposition (); +}; + +class TempoMarker : public Marker +{ + public: + TempoMarker (PublicEditor& editor, GtkCanvasGroup *parent, guint32 rgba, const string& text, ARDOUR::TempoSection&, + gint (*callback)(GtkCanvasItem *, GdkEvent *, gpointer)); + ~TempoMarker (); + + ARDOUR::TempoSection& tempo() const { return _tempo; } + + private: + ARDOUR::TempoSection& _tempo; +}; + +class MeterMarker : public Marker +{ + public: + MeterMarker (PublicEditor& editor, GtkCanvasGroup *parent, guint32 rgba, const string& text, ARDOUR::MeterSection&, + gint (*callback)(GtkCanvasItem *, GdkEvent *, gpointer)); + ~MeterMarker (); + + ARDOUR::MeterSection& meter() const { return _meter; } + + private: + ARDOUR::MeterSection& _meter; +}; + +#endif /* __gtk_ardour_marker_h__ */ diff --git a/gtk2_ardour/marker_time_axis.cc b/gtk2_ardour/marker_time_axis.cc new file mode 100644 index 0000000000..9efde933bb --- /dev/null +++ b/gtk2_ardour/marker_time_axis.cc @@ -0,0 +1,333 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include + +#include + +#include +#include + +#include "ardour_ui.h" +#include "public_editor.h" +#include "imageframe_time_axis.h" +#include "canvas-simplerect.h" +#include "selection.h" +#include "imageframe_time_axis_view.h" +#include "marker_time_axis_view.h" +#include "imageframe_view.h" +#include "marker_time_axis.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace SigC; +using namespace Gtk; + +//---------------------------------------------------------------------------------------// +// Constructor / Desctructor + +/** + * Constructs a new MarkerTimeAxis + * + * @param ed the PublicEditor + * @param sess the current session + * @param canvas the parent canvas item + * @param name the name/id of this time axis + * @param tav the associated track view that this MarkerTimeAxis is marking up + */ +MarkerTimeAxis::MarkerTimeAxis (PublicEditor& ed, ARDOUR::Session& sess, Widget *canvas, std::string name, TimeAxisView* tav) + : AxisView(sess), + VisualTimeAxis(name, ed, sess, canvas) +{ + /* the TimeAxisView these markers are associated with */ + marked_time_axis = tav ; + + _color = unique_random_color() ; + time_axis_name = name ; + + selection_group = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_display), gtk_canvas_group_get_type (), 0) ; + gtk_canvas_item_hide(selection_group) ; + + // intialize our data items + name_prompter = 0 ; + marker_menu = 0 ; + + y_position = -1 ; + + /* create our new marker time axis strip view */ + view = new MarkerTimeAxisView(*this) ; + + // set the initial time axis text label + label_view() ; + + // set the initial height of this time axis + set_height(Small) ; +} + +/** + * Destructor + * Responsible for destroying any marker items upon this time axis + */ +MarkerTimeAxis::~MarkerTimeAxis() +{ + GoingAway() ; /* EMIT_SIGNAL */ + + for (list::iterator i = free_selection_rects.begin(); i != free_selection_rects.end(); ++i) + { + gtk_object_destroy (GTK_OBJECT((*i)->rect)); + gtk_object_destroy (GTK_OBJECT((*i)->start_trim)); + gtk_object_destroy (GTK_OBJECT((*i)->end_trim)); + } + + for (list::iterator i = used_selection_rects.begin(); i != used_selection_rects.end(); ++i) + { + gtk_object_destroy (GTK_OBJECT((*i)->rect)); + gtk_object_destroy (GTK_OBJECT((*i)->start_trim)); + gtk_object_destroy (GTK_OBJECT((*i)->end_trim)); + } + + if(selection_group) + { + gtk_object_destroy(GTK_OBJECT (selection_group)) ; + selection_group = 0 ; + } + + // destroy the view helper + // this handles removing and destroying individual marker items + if(view) + { + delete view ; + view = 0 ; + } +} + + +//---------------------------------------------------------------------------------------// +// ui methods & data + +/** + * Sets the height of this TrackView to one of the defined TrackHeights + * + * @param h the TrackHeight value to set + */ +void +MarkerTimeAxis::set_height (TrackHeight h) +{ + VisualTimeAxis::set_height(h) ; + + // tell out view helper of the change too + if (view != 0) + { + view->set_height((double) height) ; + } + + // tell those interested that we have had our height changed + gui_changed("track_height",(void*)0) ; /* EMIT_SIGNAL */ +} + +/** + * Sets the number of samples per unit that are used. + * This is used to determine the sizes of items upon this time axis + * + * @param spu the number of samples per unit + */ +void +MarkerTimeAxis::set_samples_per_unit(double spu) +{ + TimeAxisView::set_samples_per_unit (editor.get_current_zoom()); + + if (view) { + view->set_samples_per_unit(spu) ; + } +} + +/** + * Show the popup edit menu + * + * @param button the mouse button pressed + * @param time when to show the popup + * @param clicked_mv the MarkerView that the event ocured upon, or 0 if none + * @param with_item true if an item has been selected upon the time axis, used to set context menu + */ +void +MarkerTimeAxis::popup_marker_time_axis_edit_menu(int button, int32_t time, MarkerView* clicked_mv, bool with_item) +{ + if (!marker_menu) + { + build_marker_menu() ; + } + + if (with_item) + { + marker_item_menu->set_sensitive(true) ; + } + else + { + marker_item_menu->set_sensitive(false) ; + } + + marker_menu->popup(button,time) ; +} + + +/** + * convenience method to select a new track color and apply it to the view and view items + * + */ +void +MarkerTimeAxis::select_track_color() +{ + if(VisualTimeAxis::choose_time_axis_color()) + { + if(view) + { + view->apply_color(_color) ; + } + } +} + +/** + * Handles the building of the popup menu + */ +void +MarkerTimeAxis::build_display_menu() +{ + using namespace Menu_Helpers; + + /* get the size menu ready */ + build_size_menu() ; + + /* prepare it */ + TimeAxisView::build_display_menu(); + + /* now fill it with our stuff */ + MenuList& items = display_menu->items(); + + items.push_back(MenuElem (_("Rename"), slot (*this, &VisualTimeAxis::start_time_axis_rename))); + + items.push_back(SeparatorElem()) ; + items.push_back(MenuElem (_("Height"), *size_menu)); + items.push_back(MenuElem (_("Color"), slot (*this, &MarkerTimeAxis::select_track_color))); + items.push_back(SeparatorElem()) ; + + items.push_back(MenuElem (_("Remove"), bind(slot(*this, &MarkerTimeAxis::remove_this_time_axis), (void*)this))); +} + +/** + * handles the building of the MarkerView sub menu + */ +void +MarkerTimeAxis::build_marker_menu() +{ + using namespace Menu_Helpers; + + marker_menu = manage(new Menu) ; + marker_menu->set_name ("ArdourContextMenu"); + MenuList& items = marker_menu->items(); + + marker_item_menu = manage(new Menu) ; + marker_item_menu->set_name ("ArdourContextMenu"); + MenuList& marker_sub_items = marker_item_menu->items() ; + + /* duration menu */ + Menu* duration_menu = manage(new Menu) ; + duration_menu->set_name ("ArdourContextMenu"); + MenuList& duration_items = duration_menu->items() ; + + if(view) + { + duration_items.push_back(MenuElem (_("1 seconds"), bind (slot (view, &MarkerTimeAxisView::set_marker_duration_sec), 1.0))) ; + duration_items.push_back(MenuElem (_("1.5 seconds"), bind (slot (view, &MarkerTimeAxisView::set_marker_duration_sec), 1.5))) ; + duration_items.push_back(MenuElem (_("2 seconds"), bind (slot (view, &MarkerTimeAxisView::set_marker_duration_sec), 2.0))) ; + duration_items.push_back(MenuElem (_("2.5 seconds"), bind (slot (view, &MarkerTimeAxisView::set_marker_duration_sec), 2.5))) ; + duration_items.push_back(MenuElem (_("3 seconds"), bind (slot (view, &MarkerTimeAxisView::set_marker_duration_sec), 3.0))) ; + } + //duration_items.push_back(SeparatorElem()) ; + //duration_items.push_back(MenuElem (_("custom"), slot (*this, &ImageFrameTimeAxis::set_marker_duration_custom))) ; + + marker_sub_items.push_back(MenuElem(_("Duration (sec)"), *duration_menu)) ; + + marker_sub_items.push_back(SeparatorElem()) ; + marker_sub_items.push_back(MenuElem (_("Remove Marker"), bind(slot(view, &MarkerTimeAxisView::remove_selected_marker_view),(void*)this))) ; + + items.push_back(MenuElem(_("Marker"), *marker_item_menu)) ; + items.push_back(MenuElem (_("Rename Track"), slot (*this,&MarkerTimeAxis::start_time_axis_rename))) ; + + marker_menu->show_all() ; +} + + + +/** + * Returns the view helper of this TimeAxis + * + * @return the view helper of this TimeAxis + */ +MarkerTimeAxisView* +MarkerTimeAxis::get_view() +{ + return(view) ; +} + +/** + * Returns the TimeAxisView that this markerTimeAxis is marking up + * + * @return the TimeAXisView that this MarkerTimeAxis is marking + */ +TimeAxisView* +MarkerTimeAxis::get_marked_time_axis() +{ + return(marked_time_axis) ; +} + + + + +/** + * Handle the closing of the renaming dialog during the rename of this item + */ +void +MarkerTimeAxis::finish_route_rename() +{ + name_prompter->hide_all (); + ARDOUR_UI::instance()->allow_focus (false); + + if (name_prompter->status == Gtkmmext::Prompter::cancelled) { + return; + } + + string result; + name_prompter->get_result(result); + time_axis_name = result ; + editor.route_name_changed(this) ; + label_view() ; + delete name_prompter ; + name_prompter = 0 ; +} + + + + + + + diff --git a/gtk2_ardour/marker_time_axis.h b/gtk2_ardour/marker_time_axis.h new file mode 100644 index 0000000000..a46025cd19 --- /dev/null +++ b/gtk2_ardour/marker_time_axis.h @@ -0,0 +1,164 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_marker_time_axis_h__ +#define __ardour_marker_time_axis_h__ + +#include +#include + +#include "ardour_dialog.h" +#include "route_ui.h" +#include "enums.h" +#include "time_axis_view.h" +#include +#include "visual_time_axis.h" + +namespace ARDOUR { + class Session; +} + +class PublicEditor; +class ImageFrameView ; +class ImageFrameTimeAxisView ; +class MarkerTimeAxisView ; +class MarkerView ; + +/** + * MarkerTimeAxis defines a visual time axis for holding marker items associated with other time axis, and time axis items. + * + * The intention of this time axis is to allow markers with duration to be arranged on the time line + * to add additional timing information to items on an associated time axis, for instance the addition + * of effect duration and timings + */ +class MarkerTimeAxis : public VisualTimeAxis +{ + public: + //---------------------------------------------------------------------------------------// + // Constructor / Desctructor + + /** + * Constructs a new MarkerTimeAxis + * + * @param ed the PublicEditor + * @param sess the current session + * @param canvas the parent canvas item + * @param name the name/id of this time axis + * @param tav the associated track view that this MarkerTimeAxis is marking up + */ + MarkerTimeAxis(PublicEditor& ed, ARDOUR::Session& sess, Gtk::Widget* canvas, std::string name, TimeAxisView* tav) ; + + /** + * Destructor + * Responsible for destroying any marker items upon this time axis + */ + virtual ~MarkerTimeAxis() ; + + + //---------------------------------------------------------------------------------------// + // ui methods & data + + /** + * Sets the height of this TrackView to one of the defined TrackHeights + * + * @param h the TrackHeight value to set + */ + virtual void set_height(TimeAxisView::TrackHeight h) ; + + /** + * Sets the number of samples per unit that are used. + * This is used to determine the sizes of items upon this time axis + * + * @param spu the number of samples per unit + */ + virtual void set_samples_per_unit(double spu) ; + + + /** + * Show the popup edit menu + * + * @param button the mouse button pressed + * @param time when to show the popup + * @param clicked_mv the MarkerView that the event ocured upon, or 0 if none + * @param with_item true if an item has been selected upon the time axis, used to set context menu + */ + void popup_marker_time_axis_edit_menu(int button, int32_t time, MarkerView* clicked_mv, bool with_item) ; + + + //---------------------------------------------------------------------------------------// + // Parent/Child helper object accessors + + /** + * Returns the view helper of this TimeAxis + * + * @return the view helper of this TimeAxis + */ + MarkerTimeAxisView* get_view() ; + + /** + * Returns the TimeAxisView that this markerTimeAxis is marking up + * + * @return the TimeAXisView that this MarkerTimeAxis is marking + */ + TimeAxisView* get_marked_time_axis() ; + + + protected: + + /** + * Handle the closing of the renaming dialog during the rename of this item + */ + virtual void finish_route_rename() ; + + private: + + /** + * convenience method to select a new track color and apply it to the view and view items + * + */ + void select_track_color() ; + + /** + * Handles the building of the popup menu + */ + virtual void build_display_menu() ; + + /** + * handles the building of the MarkerView sub menu + */ + void build_marker_menu() ; + + /** The associated TimeAxis that this MarkerTimeAxis is marking up */ + TimeAxisView* marked_time_axis ; + + /** Our time axis view helper */ + MarkerTimeAxisView *view ; + + /** the popup menu available by clicking upon this time axis */ + Gtk::Menu *marker_menu ; + + /** specialized sub menu available when clicking upon and item upon this time axis */ + Gtk::Menu *marker_item_menu ; + + +} ; /* class MarkerTimeAxis */ + +#endif /* __ardour_imageframe_time_axis_h__ */ + diff --git a/gtk2_ardour/marker_time_axis_view.cc b/gtk2_ardour/marker_time_axis_view.cc new file mode 100644 index 0000000000..b07448e1a6 --- /dev/null +++ b/gtk2_ardour/marker_time_axis_view.cc @@ -0,0 +1,400 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include +#include + +#include "marker_time_axis_view.h" +#include "marker_time_axis.h" +#include "marker_view.h" +#include "imageframe_view.h" +#include "imageframe_time_axis.h" +#include "canvas-simplerect.h" +#include "public_editor.h" +#include "rgb_macros.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace ARDOUR ; +using namespace Editing; + +//---------------------------------------------------------------------------------------// +// Constructor / Desctructor + +/** + * Construct a new MarkerTimeAxisView helper time axis helper + * + * @param mta the TimeAxsiView that this objbect is the helper for + */ +MarkerTimeAxisView::MarkerTimeAxisView(MarkerTimeAxis& tv) + : _trackview (tv) +{ + region_color = _trackview.color(); + stream_base_color = color_map[cMarkerTrackBase]; + + canvas_group = gtk_canvas_item_new (GTK_CANVAS_GROUP(_trackview.canvas_display), gtk_canvas_group_get_type (), 0); + + canvas_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_group), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 1000000.0, + "y2", (double)20, + "outline_color_rgba", color_map[cMarkerTrackOutline], + "fill_color_rgba", stream_base_color, + 0) ; + + gtk_signal_connect(GTK_OBJECT(canvas_rect), "event", (GtkSignalFunc)PublicEditor::canvas_marker_time_axis_view_event, &_trackview) ; + + _samples_per_unit = _trackview.editor.get_current_zoom() ; + + _trackview.editor.ZoomChanged.connect (slot(*this, &MarkerTimeAxisView::reset_samples_per_unit)); +} + +/** + * Destructor + * Reposinsibly for destroying all marker items that may have been added to this time axis view + * + */ +MarkerTimeAxisView::~MarkerTimeAxisView() +{ + // destroy everything upon this view + for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter) + { + MarkerView* mv = (*iter) ; + + MarkerViewList::iterator next = iter ; + next++ ; + marker_view_list.erase(iter) ; + + delete mv ; + mv = 0 ; + + iter = next ; + } + + if(canvas_rect) + { + gtk_object_destroy(GTK_OBJECT(canvas_rect)) ; + canvas_rect = 0 ; + } + + if(canvas_group) + { + gtk_object_destroy(GTK_OBJECT(canvas_group)) ; + canvas_group = 0 ; + } +} + + +//---------------------------------------------------------------------------------------// +// ui methods & data + +/** + * Sets the height of the time axis view and the item upon it + * + * @param height the new height + */ +int +MarkerTimeAxisView::set_height(gdouble h) +{ + if (h < 10.0 || h > 1000.0) + { + return -1 ; + } + + gtk_object_set (GTK_OBJECT(canvas_rect), "y2", h, NULL); + + for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i) + { + (*i)->set_height(h) ; + } + + return 0; +} + +/** + * Sets the position of this view helper on the canvas + * + * @param x the x position upon the canvas + * @param y the y position upon the canvas + */ +int +MarkerTimeAxisView::set_position(gdouble x, gdouble y) +{ + gtk_canvas_item_set (canvas_group, "x", x, "y", y, NULL); + return 0; +} + +/** + * Sets the current samples per unit. + * this method tells each item upon the time axis of the change + * + * @param spu the new samples per canvas unit value + */ +int +MarkerTimeAxisView::set_samples_per_unit(gdouble spp) +{ + if(spp < 1.0) { + return -1 ; + } + + _samples_per_unit = spp ; + + for(MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i) + { + (*i)->set_samples_per_unit(spp) ; + } + return(0) ; +} + +/** + * Sets the color of the items contained upon this view helper + * + * @param color the new base color + */ +void +MarkerTimeAxisView::apply_color(GdkColor& color) +{ + region_color = color; + + for (MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); i++) + { + (*i)->set_color (region_color) ; + } +} + + +//---------------------------------------------------------------------------------------// +// Child MarkerView Accessors/Mutators + +/** + * Adds a marker view to the list of items upon this time axis view helper + * the new MarkerView is returned + * + * @param ifv the ImageFrameView that the new item is marking up + * @param mark_text the text to be displayed uopn the new marker item + * @param mark_id the unique id of the new item + * @param start the position the new item should be placed upon the time line + * @param duration the duration the new item should be placed upon the timeline + * @param src the identity of the object that initiated the change + */ +MarkerView* +MarkerTimeAxisView::add_marker_view(ImageFrameView* ifv, std::string mark_type, std::string mark_id, jack_nframes_t start, jack_nframes_t dur, void* src) +{ + if(ifv->has_marker_view_item(mark_id)) + { + return(0) ; + } + + MarkerView* mv = new MarkerView(GTK_CANVAS_GROUP(canvas_group), + &_trackview, + ifv, + _trackview.editor.get_current_zoom(), + region_color, + mark_type, + mark_id, + start, + dur) ; + + ifv->add_marker_view_item(mv, src) ; + marker_view_list.push_front(mv) ; + + mv->GoingAway.connect(bind (slot (*this,&MarkerTimeAxisView::remove_marker_view), (void*)this)) ; + + MarkerViewAdded(mv,src) ; /* EMIT_SIGNAL */ + + return(mv) ; +} + +/** + * Returns the named MarkerView or 0 if the named marker does not exist + * + * @param item_id the unique id of the item to search for + * @return the named MarkerView, or 0 if it is not held upon this view + */ +MarkerView* +MarkerTimeAxisView::get_named_marker_view(std::string item_id) +{ + MarkerView* mv = 0 ; + + for(MarkerViewList::iterator i = marker_view_list.begin(); i != marker_view_list.end(); ++i) + { + if(((MarkerView*)*i)->get_item_name() == item_id) + { + mv = ((MarkerView*)*i) ; + break ; + } + } + return(mv) ; +} + +/** + * Removes the currently selected MarverView + * Note that this method actually destroys the MarkerView too. + * We assume that since we own the object, we are allowed to do this + * + * @param src the identity of the object that initiated the change + * @see add_marker_view + */ +void +MarkerTimeAxisView::remove_selected_marker_view(void* src) +{ + std::string removed ; + + if (selected_time_axis_item) + { + MarkerViewList::iterator i ; + if((i = find (marker_view_list.begin(), marker_view_list.end(), selected_time_axis_item)) != marker_view_list.end()) + { + marker_view_list.erase(i) ; + + MarkerViewRemoved(selected_time_axis_item->get_item_name(),src) ; /* EMIT_SIGNAL */ + + delete(selected_time_axis_item) ; + selected_time_axis_item = 0 ; + } + } + else + { + //No selected marker view + } +} + +/** + * Removes and returns the named MarkerView from the list of MarkerView held by this view helper + * + * @param item_id the MarkerView unique id to remove + * @param src the identity of the object that initiated the change + * @see add_marker_view + */ +MarkerView* +MarkerTimeAxisView::remove_named_marker_view(std::string item_id, void* src) +{ + MarkerView* mv = 0 ; + + MarkerViewList::iterator i = marker_view_list.begin() ; + + for(MarkerViewList::iterator iter = marker_view_list.begin(); iter != marker_view_list.end(); ++iter) + { + if(((MarkerView*)*i)->get_item_name() == item_id) + { + mv = ((MarkerView*)*i) ; + marker_view_list.erase(i) ; + + MarkerViewRemoved(mv->get_item_name(), src) ; /* EMIT_SIGNAL */ + + // break from the for loop + break; + } + i++ ; + } + + return(mv) ; +} + +/** + * Removes mv from the list of MarkerView upon this TimeAxis + * + * @param mv the MarkerView to remove + * @param src the identity of the object that initiated the change + */ +void +MarkerTimeAxisView::remove_marker_view(MarkerView* mv, void* src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &MarkerTimeAxisView::remove_marker_view), mv, src)); + + MarkerViewList::iterator i; + + if((i = find (marker_view_list.begin(), marker_view_list.end(), mv)) != marker_view_list.end()) { + marker_view_list.erase(i) ; + + // Assume this remove happened locally, else use remove_named_marker_time_axis + // let listeners know that the named MarkerTimeAxis has been removed + MarkerViewRemoved(mv->get_item_name(), src) ; /* EMIT_SIGNAL */ + } +} + + +/** + * Sets the duration of the selected MarkerView to the specified number of seconds + * + * @param sec the duration to set the MArkerView to, in seconds + */ +void +MarkerTimeAxisView::set_marker_duration_sec(double sec) +{ + if(get_selected_time_axis_item() != 0) + { + get_selected_time_axis_item()->set_duration((jack_nframes_t) (sec * _trackview.editor.current_session()->frame_rate()), this) ; + } +} + + +//---------------------------------------------------------------------------------------// +// Selected item methods + +/** + * Sets the currently selected item upon this time axis + * + * @param mv the item to set selected + */ +void +MarkerTimeAxisView::set_selected_time_axis_item(MarkerView* mv) +{ + selected_time_axis_item = mv ; +} + +/** + * Clears any selected item upon this time axis + * + */ +void +MarkerTimeAxisView::clear_selected_time_axis_item() +{ + selected_time_axis_item = 0 ; +} + +/** + * Returnsthe currently selected item upon this time axis + * + * @return the currently selected item pon this time axis + */ +MarkerView* +MarkerTimeAxisView::get_selected_time_axis_item() +{ + return(selected_time_axis_item) ; +} + + + + +/** + * convenience method to re-get the samples per unit and tell items upon this view + * + */ +void +MarkerTimeAxisView::reset_samples_per_unit () +{ + set_samples_per_unit(_trackview.editor.get_current_zoom()) ; +} diff --git a/gtk2_ardour/marker_time_axis_view.h b/gtk2_ardour/marker_time_axis_view.h new file mode 100644 index 0000000000..a8e86131cc --- /dev/null +++ b/gtk2_ardour/marker_time_axis_view.h @@ -0,0 +1,239 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_marker_time_axis_view_h__ +#define __ardour_marker_time_axis_view_h__ + +#include + +#include +#include + +#include + +class PublicEditor; +class MarkerTimeAxis; +class ImageFrameView ; +class MarkerView ; +class TimeAxisView ; +class TimeAxisViewItem ; + +/** + * A view helper for handling MarkerView objects. + * This object is responsible for the time axis canvas view, and + * maintains the list of items that have been added to it + */ +class MarkerTimeAxisView : public SigC::Object +{ + public: + //---------------------------------------------------------------------------------------// + // Constructor / Desctructor + + /** + * Construct a new MarkerTimeAxisView helper time axis helper + * + * @param mta the TimeAxsiView that this objbect is the helper for + */ + MarkerTimeAxisView(MarkerTimeAxis& mta) ; + + /** + * Destructor + * Reposinsibly for destroying all marker items that may have been added to this time axis view + * + */ + ~MarkerTimeAxisView () ; + + //---------------------------------------------------------------------------------------// + // Parent/Child helper object accessors + + /** + * Returns the TimeAxisView thatt his object is acting as a helper for + * + * @return the TimeAxisView that this object is acting as a view helper for + */ + MarkerTimeAxis& trackview() { return _trackview; } + + /** + * + */ + GtkCanvasItem *canvas_item() { return canvas_group; } + + + //---------------------------------------------------------------------------------------// + // ui methods & data + + /** + * Sets the height of the time axis view and the item upon it + * + * @param height the new height + */ + int set_height(gdouble height) ; + + /** + * Sets the position of this view helper on the canvas + * + * @param x the x position upon the canvas + * @param y the y position upon the canvas + */ + int set_position(gdouble x, gdouble y) ; + + /** + * Sets the current samples per unit. + * this method tells each item upon the time axis of the change + * + * @param spu the new samples per canvas unit value + */ + int set_samples_per_unit(gdouble spu) ; + + /** + * Returns the current samples per unit of this time axis view helper + * + * @return the current samples per unit of this time axis view helper + */ + gdouble get_samples_per_unit() { return _samples_per_unit; } + + /** + * Sets the color of the items contained upon this view helper + * + * @param color the new base color + */ + void apply_color(GdkColor& color) ; + + //---------------------------------------------------------------------------------------// + // Child MarkerView Accessors/Mutators + + /** + * Adds a marker view to the list of items upon this time axis view helper + * the new MarkerView is returned + * + * @param ifv the ImageFrameView that the new item is marking up + * @param mark_text the text to be displayed uopn the new marker item + * @param mark_id the unique id of the new item + * @param start the position the new item should be placed upon the time line + * @param duration the duration the new item should be placed upon the timeline + * @param src the identity of the object that initiated the change + */ + MarkerView* add_marker_view(ImageFrameView* ifv, std::string mark_type, std::string mark_id, jack_nframes_t start, jack_nframes_t dur, void* src) ; + + /** + * Returns the named MarkerView or 0 if the named marker does not exist + * + * @param item_id the unique id of the item to search for + * @return the named MarkerView, or 0 if it is not held upon this view + */ + MarkerView* get_named_marker_view(std::string item_id) ; + + /** + * Removes the currently selected MarverView + * Note that this method actually destroys the MarkerView too. + * We assume that since we own the object, we are allowed to do this + * + * @param src the identity of the object that initiated the change + * @see add_marker_view + */ + void remove_selected_marker_view(void* src) ; + + /** + * Removes and returns the named MarkerView from the list of MarkerView held by this view helper + * + * @param item_id the MarkerView unique id to remove + * @param src the identity of the object that initiated the change + * @see add_marker_view + */ + MarkerView* remove_named_marker_view(std::string item_id, void* src) ; + + /** + * Removes mv from the list of MarkerView upon this TimeAxis + * + * @param mv the MarkerView to remove + * @param src the identity of the object that initiated the change + */ + void remove_marker_view(MarkerView* item, void* src) ; + + //---------------------------------------------------------------------------------------// + // Selected item methods + + /** + * Sets the currently selected item upon this time axis + * + * @param mv the item to set selected + */ + void set_selected_time_axis_item(MarkerView* mv) ; + + /** + * Clears any selected item upon this time axis + * + */ + void clear_selected_time_axis_item() ; + + /** + * Returnsthe currently selected item upon this time axis + * + * @return the currently selected item pon this time axis + */ + MarkerView* get_selected_time_axis_item() ; + + + /** + * Sets the duration of the selected MarkerView to the specified number of seconds + * + * @param sec the duration to set the MArkerView to, in seconds + */ + void set_marker_duration_sec(double sec) ; + + //---------------------------------------------------------------------------------// + // Emitted Signals + + /** Emitted when a MarkerView is Added */ + SigC::Signal2 MarkerViewAdded ; + + /** Emitted when a MarkerView Item is removed */ + SigC::Signal2 MarkerViewRemoved ; + + private: + /** + * convenience method to re-get the samples per unit and tell items upon this view + * + */ + void reset_samples_per_unit() ; + + /** The list of items held by this time axis view helper */ + typedef std::list MarkerViewList ; + MarkerViewList marker_view_list; + + /** the currently selected time axis item upon this time axis */ + MarkerView* selected_time_axis_item ; + + /* the TimeAxisView that this object is acting as the view helper for */ + MarkerTimeAxis& _trackview ; + + GtkCanvasItem *canvas_group ; + GtkCanvasItem *canvas_rect ; /* frame around the whole thing */ + + /** the current samples per unit */ + double _samples_per_unit; + + /* XXX why are these different? */ + GdkColor region_color; + uint32_t stream_base_color; + +}; /* class MarkerTimeAxisView */ + +#endif /* __ardour_marker_time_axis_view_h__ */ diff --git a/gtk2_ardour/marker_view.cc b/gtk2_ardour/marker_view.cc new file mode 100644 index 0000000000..4c9621878e --- /dev/null +++ b/gtk2_ardour/marker_view.cc @@ -0,0 +1,142 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include "imageframe_time_axis.h" +#include "imageframe_view.h" +#include "canvas-simplerect.h" +#include "public_editor.h" +#include "marker_view.h" + +using namespace ARDOUR ; +using namespace SigC; + +SigC::Signal1 MarkerView::GoingAway; + +//---------------------------------------------------------------------------------------// +// Constructor / Desctructor + +/** + * Constructs a new MarkerView + * + * @param parent the parent canvas item + * @param tv the parent TimeAxisView of this item + * @param tavi the TimeAxisViewItem that this item is to be assciated (marking) with + * @param spu the current samples per unit + * @param base_color + * @param mark_type the marker type/name text, eg fade out, pan up etc. + * @param mark_id unique name/id of this item + * @param start the start time of this item + * @param duration the duration of this item + */ +MarkerView::MarkerView(GtkCanvasGroup *parent, + TimeAxisView* tv, + ImageFrameView* marked, + double spu, + GdkColor& basic_color, + std::string mark_type, + std::string mark_id, + jack_nframes_t start, + jack_nframes_t duration) + : TimeAxisViewItem(mark_id, parent,*tv,spu,basic_color,start,duration) +{ + mark_type_text = mark_type ; + marked_item = marked ; + + // set the canvas item text to the marker type, not the id + set_name_text(mark_type_text) ; + + // hoo up our canvas events + gtk_signal_connect (GTK_OBJECT(frame_handle_start), "event", + (GtkSignalFunc) PublicEditor::canvas_markerview_start_handle_event, + this); + + gtk_signal_connect (GTK_OBJECT(frame_handle_end), "event", + (GtkSignalFunc) PublicEditor::canvas_markerview_end_handle_event, + this); + + gtk_signal_connect (GTK_OBJECT(group), "event", + (GtkSignalFunc) PublicEditor::canvas_markerview_item_view_event, this); + + /* handle any specific details required by the initial start end duration values */ + set_position(start, this) ; + set_duration(duration, this) ; +} + +/** + * Destructor + * Destroys this Marker Item and removes the association between itself and the item it is marking. + */ +MarkerView::~MarkerView() +{ + // remove the association our marked may still have to us + if(marked_item) + { + marked_item->remove_marker_view_item(this, this) ; + } +} + + +//---------------------------------------------------------------------------------------// +// Marker Type Methods + +/** + * Sets the marker Type text of this this MarkerItem, eg fade_out, pan up etc. + * + * @param type_text the marker type text of this item + */ +void +MarkerView::set_mark_type_text(std::string type_text) +{ + mark_type_text = type_text ; + MarkTypeChanged(mark_type_text, this) ; /* EMIT_SIGNAL */ +} + +/** + * Returns the marker Type of this this MarkerItem, eg fade_out, pan up etc. + * + * @return the marker type text of this item + */ +std::string +MarkerView::get_mark_type_text() const +{ + return(mark_type_text) ; +} + + +//---------------------------------------------------------------------------------------// +// Marked Item Methods + +ImageFrameView* +MarkerView::set_marked_item(ImageFrameView* item) +{ + ImageFrameView* temp = marked_item ; + marked_item = item ; + + MarkedItemChanged(marked_item, this) ; /* EMIT_SIGNAL */ + return(temp) ; +} + +ImageFrameView* +MarkerView::get_marked_item() +{ + return(marked_item) ; +} diff --git a/gtk2_ardour/marker_view.h b/gtk2_ardour/marker_view.h new file mode 100644 index 0000000000..fdd70ffb00 --- /dev/null +++ b/gtk2_ardour/marker_view.h @@ -0,0 +1,133 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __gtk_ardour_marker_view_h__ +#define __gtk_ardour_marker_view_h__ + +#include +#include +#include +#include "time_axis_view_item.h" + +class MarkerTimeAxisView ; +class ImageFrameView ; + +/** + * MarkerView defines a marker item that may be placed upon a MarkerTimeAxis. + * + * The aim of the MarkerView is to provide additional timing details for visual based time axis. + * The MarkerView item is associated with one other TimeAxisViewItem and has a start and a duration. + */ +class MarkerView : public TimeAxisViewItem +{ + public: + //---------------------------------------------------------------------------------------// + // Constructor / Desctructor + + /** + * Constructs a new MarkerView + * + * @param parent the parent canvas item + * @param tv the parent TimeAxisView of this item + * @param marked the Item that this item is to be assciated (marking) with + * @param spu the current samples per unit + * @param base_color + * @param mark_type the marker type/name text, eg fade out, pan up etc. + * @param mark_id unique name/id of this item + * @param start the start time of this item + * @param duration the duration of this item + */ + MarkerView(GtkCanvasGroup *parent, + TimeAxisView *tv, + ImageFrameView* marked, + double spu, + GdkColor& base_color, + std::string mark_type, + std::string mark_id, + jack_nframes_t start, + jack_nframes_t duration) ; + + /** + * Destructor + * Destroys this Marker Item and removes the association between itself and the item it is marking. + */ + ~MarkerView() ; + + static SigC::Signal1 GoingAway; + + //---------------------------------------------------------------------------------------// + // Marker Type Methods + + /** + * Sets the marker Type text of this this MarkerItem, eg fade_out, pan up etc. + * + * @param type_text the marker type text of this item + */ + void set_mark_type_text(std::string type_text) ; + + /** + * Returns the marker Type of this this MarkerItem, eg fade_out, pan up etc. + * + * @return the marker type text of this item + */ + std::string get_mark_type_text() const ; + + + //---------------------------------------------------------------------------------------// + // Marked Item Methods + + /** + * Returns the time axis item being marked by this item + * + * @return the time axis item being marked by this item + */ + ImageFrameView* get_marked_item() ; + + /** + * Sets the time axis item being marker by this item + * + * @param item the time axis item to be marked by this item + * @return the previously marked item, or 0 if no previous marked item exists + */ + ImageFrameView* set_marked_item(ImageFrameView* item) ; + + //---------------------------------------------------------------------------------// + // Emitted Signals + + /** Emitted when the mark type text is changed */ + SigC::Signal2 MarkTypeChanged ; + + /** Emitted when the Marked Item is changed */ + SigC::Signal2 MarkedItemChanged ; + + + protected: + + private: + /** the unique name/id of this item */ + std::string mark_type_text ; + + /* a pointer to the time axis item this marker is assoiated(marking up) with */ + ImageFrameView* marked_item ; + +} ; /* class MarkerView */ + + +#endif /* __gtk_ardour_imageframe_view_h__ */ diff --git a/gtk2_ardour/meter_bridge.cc b/gtk2_ardour/meter_bridge.cc new file mode 100644 index 0000000000..7524ba4b35 --- /dev/null +++ b/gtk2_ardour/meter_bridge.cc @@ -0,0 +1,256 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include + +#include "ardour_ui.h" +#include "meter_bridge.h" +#include "meter_bridge_strip.h" +#include "utils.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; +using namespace SigC; + +#define FRAME_SHADOW_STYLE GTK_SHADOW_IN +#define FRAME_NAME "BaseFrame" + +MeterBridge::MeterBridge () + : ArdourDialog ("meter bridge") +{ + meter_base.set_name ("MeterBase"); + meter_frame.set_shadow_type (FRAME_SHADOW_STYLE); + meter_frame.set_name (FRAME_NAME); + meter_frame.add (meter_base); + + upper_metering_box.set_name ("AboveMeterZone"); + lower_metering_box.set_name ("BelowMeterZone"); + + metering_vbox.set_spacing (5); + metering_vbox.set_border_width (10); + metering_vbox.pack_start (upper_metering_box, false, false); + metering_vbox.pack_start (meter_frame, false, false); + metering_vbox.pack_start (lower_metering_box, false, false); + + metering_hbox.pack_start (metering_vbox, false, false); + + meter_scroll_base.set_name ("MeterScrollBase"); + meter_scroll_base.add (metering_hbox); + + meter_viewport.add (meter_scroll_base); + meter_viewport.set_shadow_type (GTK_SHADOW_NONE); + + meter_scroller.add (meter_viewport); + meter_scroller.set_name ("MeterBridgeWindow"); + meter_scroller.set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + meter_scroller.set_border_width (5); + + add (meter_scroller); + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK); + set_name ("MeterBridgeWindow"); + set_title (_("ardour: meter bridge")); + set_wmclass (_("ardour_meter_bridge"), "Ardour"); + // set_policy (false, false, false); // no user resizing of any kind + + delete_event.connect (bind (slot (just_hide_it), static_cast(this))); + + metering = false; + + /* don't show: this window doesn't come up by default */ +} + +MeterBridge::~MeterBridge () +{ + stop_metering (); +} + +void +MeterBridge::set_session (Session *s) +{ + ArdourDialog::set_session (s); + + if (session) { + // XXX this stuff has to be fixed if we ever use this code again + // (refs vs. ptrs) + // session->foreach_route (this, &MeterBridge::add_route); + session->RouteAdded.connect (slot (*this, &MeterBridge::add_route)); + session->going_away.connect (slot (*this, &MeterBridge::session_gone)); + start_metering (); + } +} + +void +MeterBridge::session_gone () +{ + ENSURE_GUI_THREAD(slot (*this, &MeterBridge::session_gone)); + + stop_metering (); + hide_all (); + + list::iterator i; + + for (i = meters.begin(); i != meters.end(); ++i) { + + upper_metering_box.remove ((*i)->above_box()); + meter_base.remove ((*i)->meter_widget()); + lower_metering_box.remove ((*i)->below_box()); + +// delete (*i); + } + + meters.clear (); + + ArdourDialog::session_gone(); +} + +void +MeterBridge::add_route (ARDOUR::Route* route) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &MeterBridge::add_route), route)); + + uint32_t n; + char buf[32]; + + if (!session || route->hidden() || dynamic_cast(route) == 0) { + return; + } + + n = meters.size(); + snprintf (buf, sizeof (buf), "%u", n+1); + + MeterBridgeStrip *meter = new MeterBridgeStrip (session->engine(), + *session, + *route, + buf, + session->over_length_long, + session->over_length_short, + 200); + +#define packing_factor 30 + + upper_metering_box.put (meter->above_box(), n * packing_factor, 0); + + meter_base.put (meter->meter_widget(), (n * packing_factor) + (meter->meter_width()/2), 0); + lower_metering_box.put (meter->below_box(), n * packing_factor, 0); + + meter->above_box().show_all (); + meter->meter_widget().show (); + meter->below_box().show_all (); + + route->GoingAway.connect (bind (slot (*this, &MeterBridge::remove_route), route)); + meters.insert (meters.begin(), meter); + + set_default_size (30 + ((n+1) * packing_factor), 315); + + meter->set_meter_on(true); + + session->going_away.connect (slot (*this, &MeterBridge::session_gone)); +} + +void +MeterBridge::remove_route (Route* route) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &MeterBridge::remove_route), route)); + list::iterator i; + + for (i = meters.begin(); i != meters.end(); ++i) { + if (&((*i)->route()) == route) { + delete *i; + meters.erase (i); + return; + } + } +} + +void +MeterBridge::clear_all_meters () +{ + list::iterator i; + + for (i = meters.begin(); i != meters.end(); ++i) { + (*i)->clear_meter (); + } +} + +void +MeterBridge::update () +{ + list::iterator i; + + for (i = meters.begin(); i != meters.end(); ++i) { + (*i)->update (); + } +} + +void +MeterBridge::start_metering () +{ + list::iterator i; + + for (i = meters.begin(); i != meters.end(); ++i) { + (*i)->set_meter_on (true); + } + metering_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect + (slot (*this, &MeterBridge::update)); + metering = true; +} + +void +MeterBridge::stop_metering () +{ + list::iterator i; + + for (i = meters.begin(); i != meters.end(); ++i) { + (*i)->set_meter_on (false); + } + metering_connection.disconnect(); + metering = false; +} + +void +MeterBridge::toggle_metering () +{ + if (!metering) { + start_metering (); + } else { + stop_metering (); + } +} + +gint +MeterBridge::map_event_impl (GdkEventAny *ev) +{ + start_metering (); + return Window::map_event_impl (ev); +} + +gint +MeterBridge::unmap_event_impl (GdkEventAny *ev) +{ + stop_metering (); + return Window::unmap_event_impl (ev); +} + diff --git a/gtk2_ardour/meter_bridge.h b/gtk2_ardour/meter_bridge.h new file mode 100644 index 0000000000..3cb72a1629 --- /dev/null +++ b/gtk2_ardour/meter_bridge.h @@ -0,0 +1,90 @@ +/* + Copyright (C) 1999-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_meter_bridge_h__ +#define __ardour_meter_bridge_h__ + +#include + +#include +#include +#include +#include +#include +#include + +#include "keyboard_target.h" +#include "ardour_dialog.h" + +class MeterBridgeStrip; + +namespace ARDOUR { + class Session; + class Route; +} + +class MeterBridge : public ArdourDialog +{ + + public: + MeterBridge (); + ~MeterBridge (); + + void set_session (ARDOUR::Session*); + void clear_all_meters (); + void start_metering (); + void stop_metering (); + void toggle_metering (); + + protected: + gint map_event_impl (GdkEventAny *); + gint unmap_event_impl (GdkEventAny *); + + private: + /* diskstream/recorder display */ + + Gtk::Viewport meter_viewport; + Gtk::ScrolledWindow meter_scroller; + Gtk::EventBox meter_scroll_base; + Gtk::HBox meter_scroller_hpacker; + Gtk::VBox meter_scroller_vpacker; + Gtk::VBox metering_vpacker; + Gtk::VBox metering_hpacker; + + Gtk::VBox metering_vbox; + Gtk::HBox metering_hbox; + Gtk::Fixed upper_metering_box; + Gtk::Fixed lower_metering_box; + Gtk::Fixed meter_base; + Gtk::Frame meter_frame; + + list meters; + + bool metering; + SigC::Connection metering_connection; + + void update (); + + void add_route (ARDOUR::Route*); + void remove_route (ARDOUR::Route*); + void session_gone(); /* overrides ArdourDialog::session_gone() */ +}; + +#endif /* __ardour_meter_bridge_h__ (*/ diff --git a/gtk2_ardour/meter_bridge_strip.cc b/gtk2_ardour/meter_bridge_strip.cc new file mode 100644 index 0000000000..046c138827 --- /dev/null +++ b/gtk2_ardour/meter_bridge_strip.cc @@ -0,0 +1,238 @@ +/* + Copyright (C) 1999 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "meter_bridge_strip.h" +#include "ardour_ui.h" +#include "prompter.h" +#include "logmeter.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; +using namespace Gtkmmext; + +MeterBridgeStrip::MeterBridgeStrip (AudioEngine &eng, + Session& s, + Route& r, + string name, + jack_nframes_t long_over, + jack_nframes_t short_over, + jack_nframes_t meter_hold) + : engine (eng), + session (s), + _route (r), + meter (meter_hold, 5, FastMeter::Vertical) +{ + char buf[64]; + + label.set_text (name); + label.set_name ("ChannelMeterLabel"); + + label_ebox.set_name ("MeterBridgeWindow"); + label_ebox.set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK); + label_ebox.add (label); + + label_ebox.button_release_event.connect (slot (*this, &MeterBridgeStrip::label_button_press_release)); + ARDOUR_UI::instance()->tooltips().set_tip (label_ebox, _route.name()); + + over_long_label.set_text ("0"); + over_long_label.set_name ("OverMeterLabel"); + over_long_button.add (over_long_label); + over_long_button.set_name ("OverMeter"); + over_long_frame.add (over_long_button); + over_long_frame.set_shadow_type (GTK_SHADOW_IN); + over_long_frame.set_name ("BaseFrame"); + over_long_hbox.pack_start (over_long_frame, false, false); + + snprintf(buf, sizeof(buf)-1, _("# of %u-sample overs"), long_over); + ARDOUR_UI::instance()->tooltips().set_tip (over_long_button, buf); + + set_usize_to_display_given_text (over_long_button, "88g", 2, 2); + + over_short_label.set_text ("0"); + over_short_label.set_name ("OverMeterLabel"); + over_short_button.add (over_short_label); + over_short_button.set_name ("OverMeter"); + over_short_frame.add (over_short_button); + over_short_frame.set_shadow_type (GTK_SHADOW_IN); + over_short_frame.set_name ("BaseFrame"); + over_short_hbox.pack_start (over_short_frame, false, false); + + snprintf(buf, sizeof(buf)-1, _("# of %u-sample overs"), short_over); + ARDOUR_UI::instance()->tooltips().set_tip (over_short_button, buf); + + set_usize_to_display_given_text (over_short_button, "88g", 2, 2); + above_meter_vbox.set_spacing (5); + below_meter_vbox.set_spacing (5); + + above_meter_vbox.pack_start (over_long_hbox, false, false); + above_meter_vbox.pack_start (over_short_hbox, false, false); + + below_meter_vbox.pack_start (label_ebox); + + over_short_button.button_release_event.connect (slot (*this,&MeterBridgeStrip::gui_clear_overs)); + over_long_button.button_release_event.connect (slot (*this,&MeterBridgeStrip::gui_clear_overs)); + + last_over_short = 0; + last_over_long = 0; + + meter_clear_pending = false; + over_clear_pending = false; + + meter_on = true; +} + +void +MeterBridgeStrip::update () +{ + string buf; + Port *port; + guint32 over_short = 0; + guint32 over_long = 0; + + if ((port = _route.input (0)) == 0) { + meter.set (0.0); + return; + } else { + over_short = port->short_overs (); + over_long = port->long_overs (); + } + + if (meter_on) { + float power = minus_infinity(); + + if ((power = _route.peak_input_power (0)) != minus_infinity()) { + meter.set (log_meter (power)); + + if (over_short != last_over_short) { + buf = compose("%1", over_short); + over_short_label.set_text (buf); + last_over_short = over_short; + } + + if (over_long != last_over_long) { + buf = compose("%1", over_long); + over_long_label.set_text (buf); + last_over_long = over_long; + } + + } else { + meter.set (0.0); + } + + } + + if (meter_clear_pending) { + meter_clear_pending = false; + meter.clear (); + } + + if (over_clear_pending) { + over_clear_pending = false; + port->reset_overs (); + over_long_label.set_text ("0"); + over_short_label.set_text ("0"); + last_over_short = 0; + last_over_long = 0; + } +} + +gint +MeterBridgeStrip::gui_clear_overs (GdkEventButton *ev) +{ + clear_overs (); + return FALSE; +} + +void +MeterBridgeStrip::clear_meter () + +{ + meter_clear_pending = true; +} + +void +MeterBridgeStrip::clear_overs () + +{ + over_clear_pending = true; +} + +void +MeterBridgeStrip::set_meter_on (bool yn) +{ + Port* port; + meter_on = yn; + + if (!meter_on) { + meter_clear_pending = true; + over_clear_pending = true; + } + + if (meter.is_visible()) { + if ((port = _route.input (0)) != 0) { + if (meter_on) { + port->enable_metering (); + } else { + port->disable_metering (); + } + } + } +} + +gint +MeterBridgeStrip::label_button_press_release (GdkEventButton *ev) +{ + ArdourPrompter prompter (true); + prompter.set_prompt (_("New name for meter:")); + prompter.set_initial_text (label.get_text()); + prompter.done.connect (Gtk::Main::quit.slot()); + prompter.show_all(); + + Gtk::Main::run(); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string name; + + prompter.get_result (name); + + if (name.length()) { + label.set_text(name); + } + } + + return FALSE; +} + diff --git a/gtk2_ardour/meter_bridge_strip.h b/gtk2_ardour/meter_bridge_strip.h new file mode 100644 index 0000000000..932c2de925 --- /dev/null +++ b/gtk2_ardour/meter_bridge_strip.h @@ -0,0 +1,104 @@ +/* + Copyright (C) 1999 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_meterbridgestrip_h__ +#define __ardour_meterbridgestrip_h__ + +#include +#include +#include + +namespace ARDOUR { + class AudioEngine; + class Session; + class Route; +} + +namespace Gtkmmext { + class Selector; + struct SelectionResult; +} + +class MeterBridgeStrip : public SigC::Object + +{ + public: + MeterBridgeStrip (ARDOUR::AudioEngine &, + ARDOUR::Session&, + ARDOUR::Route&, + string label, + jack_nframes_t long_over, + jack_nframes_t short_over, + jack_nframes_t meter_hold); + + void update (); /* called by meter timeout handler from ARDOUR_UI */ + + Gtk::Box &above_box() { return above_meter_vbox; } + Gtk::Box &below_box() { return below_meter_vbox; } + Gtk::Widget &meter_widget() { return meter; } + + guint32 meter_width() const { return 8; } + + void clear_meter (); + void clear_overs (); + + void set_meter_on (bool yn); + bool get_meter_on () const { return meter_on; } + + ARDOUR::Route& route() const { return _route; } + + private: + ARDOUR::AudioEngine& engine; + ARDOUR::Session& session; + ARDOUR::Route& _route; + + Gtk::EventBox label_ebox; + Gtk::Label label; + bool meter_clear_pending; + bool over_clear_pending; + + Gtkmmext::FastMeter meter; + bool meter_on; + + Gtk::VBox above_meter_vbox; + Gtk::VBox below_meter_vbox; + + Gtk::HBox over_long_hbox; + Gtk::HBox over_long_vbox; + Gtk::EventBox over_long_button; + Gtk::Frame over_long_frame; + Gtk::Label over_long_label; + + Gtk::HBox over_short_hbox; + Gtk::HBox over_short_vbox; + Gtk::EventBox over_short_button; + Gtk::Frame over_short_frame; + Gtk::Label over_short_label; + + guint32 last_over_short; + guint32 last_over_long; + + gint gui_clear_overs (GdkEventButton *); + gint label_button_press_release (GdkEventButton *); +}; + +#endif /* __ardour_meterbridgestrip_h__ */ + + diff --git a/gtk2_ardour/misc_xpms b/gtk2_ardour/misc_xpms new file mode 100644 index 0000000000..026303066e --- /dev/null +++ b/gtk2_ardour/misc_xpms @@ -0,0 +1,632 @@ +/* XPM */ +static const char * vslider_rail_xpm[] = { +"3 200 4 1", +" c None", +". c #000000", +", c #424242", +"+ c #969393", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+", +".,+"}; + +/* XPM */ +static const char * vslider_slider_xpm_16wide[] = { +"16 32 176 2", +" c None", +". c #999991", +"+ c #A1A198", +"@ c #A0A097", +"# c #9E9E95", +"$ c #9D9D94", +"% c #9C9C93", +"& c #9A9A92", +"* c #999990", +"= c #98988F", +"- c #96968E", +"; c #95958D", +"> c #94948B", +", c #93938A", +"' c #919189", +") c #575751", +"! c #97978F", +"~ c #A3A39A", +"{ c #A0A098", +"] c #9F9F96", +"^ c #989890", +"/ c #81817A", +"( c #3D3D39", +"_ c #94948C", +": c #B0B0A8", +"< c #C8C8C1", +"[ c #C7C7C1", +"} c #C7C7C0", +"| c #C6C6C0", +"1 c #C6C6BF", +"2 c #C5C5BF", +"3 c #C5C5BE", +"4 c #C4C4BD", +"5 c #71716C", +"6 c #3C3C38", +"7 c #93938B", +"8 c #8F8F87", +"9 c #858580", +"0 c #85857F", +"a c #84847F", +"b c #5C5C58", +"c c #3C3C39", +"d c #878781", +"e c #878782", +"f c #5A5A56", +"g c #3D3D3A", +"h c #94948F", +"i c #5B5B57", +"j c #3E3E3A", +"k c #9F9F9A", +"l c #A0A09A", +"m c #5C5C57", +"n c #3E3E3B", +"o c #92928A", +"p c #9B9B93", +"q c #AAAAA4", +"r c #AAAAA5", +"s c #3F3F3B", +"t c #B3B3AD", +"u c #B2B2AD", +"v c #B2B2AC", +"w c #3F3F3C", +"x c #929289", +"y c #9D9D95", +"z c #BABAB3", +"A c #BABAB4", +"B c #B9B9B3", +"C c #B8B8B2", +"D c #40403C", +"E c #9E9E96", +"F c #C0C0BA", +"G c #C0C0B9", +"H c #BFBFB9", +"I c #BFBFB8", +"J c #BEBEB8", +"K c #40403D", +"L c #909088", +"M c #C4C4BE", +"N c #C3C3BD", +"O c #C3C3BC", +"P c #C2C2BC", +"Q c #5B5B56", +"R c #41413D", +"S c #878780", +"T c #A1A19C", +"U c #A1A19D", +"V c #A0A09B", +"W c #4B4B47", +"X c #8E8E86", +"Y c #434340", +"Z c #323232", +"` c #333333", +" . c #1D1D1C", +".. c #8D8D85", +"+. c #8C8C84", +"@. c #A7A7A2", +"#. c #A6A6A1", +"$. c #A6A6A0", +"%. c #A5A5A0", +"&. c #8B8B83", +"*. c #D1D1CA", +"=. c #D0D0C9", +"-. c #CFCFC9", +";. c #CFCFC8", +">. c #CECEC7", +",. c #8A8A82", +"'. c #D2D2CB", +"). c #D2D2CA", +"!. c #898981", +"~. c #9F9F97", +"{. c #D0D0C8", +"]. c #5D5D59", +"^. c #D1D1C9", +"/. c #CFCFC7", +"(. c #5F5F5A", +"_. c #86867F", +":. c #CECEC6", +"<. c #CDCDC6", +"[. c #CDCDC5", +"}. c #60605B", +"|. c #85857D", +"1. c #A1A199", +"2. c #CCCCC5", +"3. c #CCCCC4", +"4. c #CBCBC4", +"5. c #CBCBC3", +"6. c #CACAC3", +"7. c #62625D", +"8. c #83837C", +"9. c #CACAC2", +"0. c #C9C9C1", +"a. c #C8C8C0", +"b. c #C7C7BF", +"c. c #64645F", +"d. c #82827B", +"e. c #A4A49B", +"f. c #C5C5BD", +"g. c #C4C4BC", +"h. c #C3C3BB", +"i. c #C2C2BA", +"j. c #C1C1B9", +"k. c #C0C0B8", +"l. c #656560", +"m. c #818179", +"n. c #A5A59D", +"o. c #BDBDB5", +"p. c #BDBDB4", +"q. c #BCBCB4", +"r. c #BBBBB3", +"s. c #BABAB2", +"t. c #B9B9B1", +"u. c #B8B8B0", +"v. c #666661", +"w. c #7F7F78", +"x. c #B6B6AE", +"y. c #B6B6AD", +"z. c #B5B5AD", +"A. c #B5B5AC", +"B. c #B4B4AC", +"C. c #B3B3AB", +"D. c #B2B2AB", +"E. c #B2B2AA", +"F. c #B1B1A9", +"G. c #696964", +"H. c #7D7D76", +"I. c #BEBEB7", +"J. c #BDBDB7", +"K. c #6E6E6A", +"L. c #7B7B74", +"M. c #60605A", +"N. c #50504B", +"O. c #4D4D49", +"P. c #6B6B65", +"Q. c #484844", +"R. c #454541", +"S. c #42423E", +". + @ # $ % & * * = - ; > , ' ) ", +"! ~ { ] # $ % & & . ^ ! - ; / ( ", +"_ : < < [ } } | | 1 1 2 3 4 5 6 ", +"7 8 9 9 9 9 9 9 9 9 0 0 0 a b c ", +"7 8 d e e e e e e e e e e d f g ", +"7 ; h h h h h h h h h h h h i j ", +"7 ^ k k l l l l l l l k k k m n ", +"o p q r r r r r r r r q q q m s ", +"o $ t t t t t t t t u v v v m w ", +"x y z A A A A B B B B B C C i D ", +"' E F F F F F F F G H H I J i K ", +"L E M M M M M 4 4 4 N N O P Q R ", +"8 E [ [ [ [ [ } } } | | 1 2 f R ", +"8 S T U U U T T T T T V V V W R ", +"X Y Z Z Z Z ` ` ` Z Z Z Z Z .R ", +"..Y Z ` ` ` ` ` ` ` ` ` Z Z .R ", +"+.S @.@.@.@.#.#.#.#.#.$.%.%.W R ", +"&.E *.*.*.*.=.=.=.=.-.;.;.>.i R ", +",.] '.'.'.).*.*.*.*.=.=.;.;.b R ", +"!.~.'.'.'.'.).*.*.*.=.=.{.;.].K ", +"S @ ).*.*.*.*.^.^.=.{.;./.>.(.D ", +"_.+ {.{.{.{.;./././.>.:.<.[.}.w ", +"|.1.:.:.:.<.[.[.[.2.3.4.5.6.7.s ", +"8.~ 6.9.9.9.0.0.0.< a.} b.1 c.n ", +"d.e.f.g.g.g.h.h.h.i.i.j.j.k.l.j ", +"m.n.o.p.q.q.r.r.r.s.s.t.t.u.v.g ", +"w.e.x.x.y.z.A.B.B.C.C.D.E.F.G.c ", +"H.. J J J J J J J J J I.J.J.K.6 ", +"L.M.N.N.N.N.N.N.N.N.N.N.N.N.O.6 ", +"P.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.D ", +"O.R.R.R.R.R.R.R.R.R.R.R.R.R.R.S.", +"O.R.R.R.R.R.R.R.R.R.R.R.R.R.R.S."}; + + +/* XPM */ +static const char * vslider_slider_xpm[] = { +"15 32 176 2", +" c None", +". c #999991", +"+ c #A1A198", +"@ c #A0A097", +"# c #9E9E95", +"$ c #9D9D94", +"% c #9C9C93", +"& c #9A9A92", +"* c #999990", +"= c #98988F", +"- c #96968E", +"; c #95958D", +"> c #94948B", +", c #93938A", +"' c #919189", +") c #575751", +"! c #97978F", +"~ c #A3A39A", +"{ c #A0A098", +"] c #9F9F96", +"^ c #989890", +"/ c #81817A", +"( c #3D3D39", +"_ c #94948C", +": c #B0B0A8", +"< c #C8C8C1", +"[ c #C7C7C1", +"} c #C7C7C0", +"| c #C6C6C0", +"1 c #C6C6BF", +"2 c #C5C5BF", +"3 c #C5C5BE", +"4 c #C4C4BD", +"5 c #71716C", +"6 c #3C3C38", +"7 c #93938B", +"8 c #8F8F87", +"9 c #858580", +"0 c #85857F", +"a c #84847F", +"b c #5C5C58", +"c c #3C3C39", +"d c #878781", +"e c #878782", +"f c #5A5A56", +"g c #3D3D3A", +"h c #94948F", +"i c #5B5B57", +"j c #3E3E3A", +"k c #9F9F9A", +"l c #A0A09A", +"m c #5C5C57", +"n c #3E3E3B", +"o c #92928A", +"p c #9B9B93", +"q c #AAAAA4", +"r c #AAAAA5", +"s c #3F3F3B", +"t c #B3B3AD", +"u c #B2B2AD", +"v c #B2B2AC", +"w c #3F3F3C", +"x c #929289", +"y c #9D9D95", +"z c #BABAB3", +"A c #BABAB4", +"B c #B9B9B3", +"C c #B8B8B2", +"D c #40403C", +"E c #9E9E96", +"F c #C0C0BA", +"G c #C0C0B9", +"H c #BFBFB9", +"I c #BFBFB8", +"J c #BEBEB8", +"K c #40403D", +"L c #909088", +"M c #C4C4BE", +"N c #C3C3BD", +"O c #C3C3BC", +"P c #C2C2BC", +"Q c #5B5B56", +"R c #41413D", +"S c #878780", +"T c #A1A19C", +"U c #A1A19D", +"V c #A0A09B", +"W c #4B4B47", +"X c #8E8E86", +"Y c #434340", +"Z c #323232", +"` c #333333", +" . c #1D1D1C", +".. c #8D8D85", +"+. c #8C8C84", +"@. c #A7A7A2", +"#. c #A6A6A1", +"$. c #A6A6A0", +"%. c #A5A5A0", +"&. c #8B8B83", +"*. c #D1D1CA", +"=. c #D0D0C9", +"-. c #CFCFC9", +";. c #CFCFC8", +">. c #CECEC7", +",. c #8A8A82", +"'. c #D2D2CB", +"). c #D2D2CA", +"!. c #898981", +"~. c #9F9F97", +"{. c #D0D0C8", +"]. c #5D5D59", +"^. c #D1D1C9", +"/. c #CFCFC7", +"(. c #5F5F5A", +"_. c #86867F", +":. c #CECEC6", +"<. c #CDCDC6", +"[. c #CDCDC5", +"}. c #60605B", +"|. c #85857D", +"1. c #A1A199", +"2. c #CCCCC5", +"3. c #CCCCC4", +"4. c #CBCBC4", +"5. c #CBCBC3", +"6. c #CACAC3", +"7. c #62625D", +"8. c #83837C", +"9. c #CACAC2", +"0. c #C9C9C1", +"a. c #C8C8C0", +"b. c #C7C7BF", +"c. c #64645F", +"d. c #82827B", +"e. c #A4A49B", +"f. c #C5C5BD", +"g. c #C4C4BC", +"h. c #C3C3BB", +"i. c #C2C2BA", +"j. c #C1C1B9", +"k. c #C0C0B8", +"l. c #656560", +"m. c #818179", +"n. c #A5A59D", +"o. c #BDBDB5", +"p. c #BDBDB4", +"q. c #BCBCB4", +"r. c #BBBBB3", +"s. c #BABAB2", +"t. c #B9B9B1", +"u. c #B8B8B0", +"v. c #666661", +"w. c #7F7F78", +"x. c #B6B6AE", +"y. c #B6B6AD", +"z. c #B5B5AD", +"A. c #B5B5AC", +"B. c #B4B4AC", +"C. c #B3B3AB", +"D. c #B2B2AB", +"E. c #B2B2AA", +"F. c #B1B1A9", +"G. c #696964", +"H. c #7D7D76", +"I. c #BEBEB7", +"J. c #BDBDB7", +"K. c #6E6E6A", +"L. c #7B7B74", +"M. c #60605A", +"N. c #50504B", +"O. c #4D4D49", +"P. c #6B6B65", +"Q. c #484844", +"R. c #454541", +"S. c #42423E", +". + @ # $ % & * = - ; > , ' ) ", +"! ~ { ] # $ % & . ^ ! - ; / ( ", +"_ : < < [ } } | 1 1 2 3 4 5 6 ", +"7 8 9 9 9 9 9 9 9 0 0 0 a b c ", +"7 8 d e e e e e e e e e d f g ", +"7 ; h h h h h h h h h h h i j ", +"7 ^ k k l l l l l l k k k m n ", +"o p q r r r r r r r q q q m s ", +"o $ t t t t t t t u v v v m w ", +"x y z A A A A B B B B C C i D ", +"' E F F F F F F G H H I J i K ", +"L E M M M M M 4 4 N N O P Q R ", +"8 E [ [ [ [ [ } } | | 1 2 f R ", +"8 S T U U U T T T T V V V W R ", +"X Y Z Z Z Z ` ` Z Z Z Z Z .R ", +"..Y Z ` ` ` ` ` ` ` ` Z Z .R ", +"+.S @.@.@.@.#.#.#.#.$.%.%.W R ", +"&.E *.*.*.*.=.=.=.-.;.;.>.i R ", +",.] '.'.'.).*.*.*.=.=.;.;.b R ", +"!.~.'.'.'.'.).*.*.=.=.{.;.].K ", +"S @ ).*.*.*.*.^.=.{.;./.>.(.D ", +"_.+ {.{.{.{.;././.>.:.<.[.}.w ", +"|.1.:.:.:.<.[.[.2.3.4.5.6.7.s ", +"8.~ 6.9.9.9.0.0.< a.} b.1 c.n ", +"d.e.f.g.g.g.h.h.i.i.j.j.k.l.j ", +"m.n.o.p.q.q.r.r.s.s.t.t.u.v.g ", +"w.e.x.x.y.z.A.B.C.C.D.E.F.G.c ", +"H.. J J J J J J J J I.J.J.K.6 ", +"L.M.N.N.N.N.N.N.N.N.N.N.N.O.6 ", +"P.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.Q.D ", +"O.R.R.R.R.R.R.R.R.R.R.R.R.R.S.", +"O.R.R.R.R.R.R.R.R.R.R.R.R.R.S."}; diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc new file mode 100644 index 0000000000..d0b3240689 --- /dev/null +++ b/gtk2_ardour/mixer_strip.cc @@ -0,0 +1,1466 @@ +/* + Copyright (C) 2000-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ardour_ui.h" +#include "ardour_dialog.h" +#include "ardour_message.h" +#include "mixer_strip.h" +#include "mixer_ui.h" +#include "keyboard.h" +#include "plugin_selector.h" +#include "public_editor.h" + +#include "plugin_ui.h" +#include "send_ui.h" +#include "io_selector.h" +#include "utils.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; +using namespace Gtkmmext; + +/* XPM */ +static const gchar * small_x_xpm[] = { +"11 11 2 1", +" c None", +". c #cccc99", +" ", +" ", +" . . ", +" . . ", +" . . ", +" . ", +" . . ", +" . . ", +" . . ", +" ", +" "}; + +/* XPM */ +static const gchar * lr_xpm[] = { +"11 11 2 1", +" c None", +". c #cccc99", +" ", +" ", +" . . ", +" . . ", +" . . ", +"...........", +" . . ", +" . . ", +" . . ", +" ", +" "}; + +static void +speed_printer (char buf[32], Gtk::Adjustment& adj, void* arg) +{ + float val = adj.get_value (); + + if (val == 1.0) { + strcpy (buf, "1"); + } else { + snprintf (buf, 32, "%.3f", val); + } +} + +MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, Route& rt, bool in_mixer) + : AxisView(sess), + RouteUI (rt, sess, _("mute"), _("solo"), _("RECORD")), + _mixer(mx), + pre_redirect_box (PreFader, sess, rt, mx.plugin_selector(), mx.selection(), in_mixer), + post_redirect_box (PostFader, sess, rt, mx.plugin_selector(), mx.selection(), in_mixer), + gpm (_route, sess), + panners (_route, sess), + button_table (8, 2), + gain_automation_style_button (""), + gain_automation_state_button (""), + pan_automation_style_button (""), + pan_automation_state_button (""), + polarity_button (_("polarity")), + comment_button (_("comments")), + speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1), + speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true) + +{ + if (set_color_from_route()) { + set_color (unique_random_color()); + } + + input_selector = 0; + output_selector = 0; + group_menu = 0; + _marked_for_display = false; + route_ops_menu = 0; + ignore_comment_edit = false; + ignore_toggle = false; + ignore_speed_adjustment = false; + comment_window = 0; + + width_button.add (*(manage (new Gtk::Pixmap (lr_xpm)))); + hide_button.add (*(manage (new Gtk::Pixmap (small_x_xpm)))); + + + input_label.set_text (_("INPUT")); + input_button.add (input_label); + input_button.set_name ("MixerIOButton"); + input_label.set_name ("MixerIOButtonLabel"); + + output_label.set_text (_("OUTPUT")); + output_button.add (output_label); + output_button.set_name ("MixerIOButton"); + output_label.set_name ("MixerIOButtonLabel"); + + rec_enable_button->set_name ("MixerRecordEnableButton"); + rec_enable_button->unset_flags (GTK_CAN_FOCUS); + + solo_button->set_name ("MixerSoloButton"); + mute_button->set_name ("MixerMuteButton"); + gain_automation_style_button.set_name ("MixerAutomationModeButton"); + gain_automation_state_button.set_name ("MixerAutomationPlaybackButton"); + pan_automation_style_button.set_name ("MixerAutomationModeButton"); + pan_automation_state_button.set_name ("MixerAutomationPlaybackButton"); + polarity_button.set_name ("MixerPhaseInvertButton"); + + ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_state_button, _("Pan automation mode")); + ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_state_button, _("Gain automation mode")); + + ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_style_button, _("Pan automation type")); + ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_style_button, _("Gain automation type")); + + hide_button.set_events (hide_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + + width_button.unset_flags (GTK_CAN_FOCUS); + hide_button.unset_flags (GTK_CAN_FOCUS); + input_button.unset_flags (GTK_CAN_FOCUS); + output_button.unset_flags (GTK_CAN_FOCUS); + solo_button->unset_flags (GTK_CAN_FOCUS); + mute_button->unset_flags (GTK_CAN_FOCUS); + gain_automation_style_button.unset_flags (GTK_CAN_FOCUS); + gain_automation_state_button.unset_flags (GTK_CAN_FOCUS); + pan_automation_style_button.unset_flags (GTK_CAN_FOCUS); + pan_automation_state_button.unset_flags (GTK_CAN_FOCUS); + polarity_button.unset_flags (GTK_CAN_FOCUS); + + button_table.set_homogeneous (true); + + button_table.attach (name_button, 0, 2, 0, 1); + button_table.attach (group_button, 0, 2, 1, 2); + button_table.attach (input_button, 0, 2, 2, 3); + + button_table.attach (polarity_button, 0, 2, 3, 4); + + button_table.attach (*solo_button, 0, 1, 4, 5); + button_table.attach (*mute_button, 1, 2, 4, 5); + + // button_table.attach (gain_automation_style_button, 0, 1, 5, 6); + button_table.attach (gain_automation_state_button, 0, 1, 5, 6); + // button_table.attach (pan_automation_style_button, 0, 1, 6, 7); + button_table.attach (pan_automation_state_button, 1, 2, 5, 6); + + using namespace Menu_Helpers; + + gain_astate_menu.items().push_back (MenuElem (_("off"), + bind (slot (_route, &IO::set_gain_automation_state), (AutoState) Off))); + gain_astate_menu.items().push_back (MenuElem (_("play"), + bind (slot (_route, &IO::set_gain_automation_state), (AutoState) Play))); + gain_astate_menu.items().push_back (MenuElem (_("write"), + bind (slot (_route, &IO::set_gain_automation_state), (AutoState) Write))); + gain_astate_menu.items().push_back (MenuElem (_("touch"), + bind (slot (_route, &IO::set_gain_automation_state), (AutoState) Touch))); + + gain_astyle_menu.items().push_back (MenuElem (_("trim"))); + gain_astyle_menu.items().push_back (MenuElem (_("abs"))); + + pan_astate_menu.items().push_back (MenuElem (_("off"), + bind (slot (_route.panner(), &Panner::set_automation_state), (AutoState) Off))); + pan_astate_menu.items().push_back (MenuElem (_("play"), + bind (slot (_route.panner(), &Panner::set_automation_state), (AutoState) Play))); + pan_astate_menu.items().push_back (MenuElem (_("write"), + bind (slot (_route.panner(), &Panner::set_automation_state), (AutoState) Write))); + pan_astate_menu.items().push_back (MenuElem (_("touch"), + bind (slot (_route.panner(), &Panner::set_automation_state), (AutoState) Touch))); + + pan_astyle_menu.items().push_back (MenuElem (_("trim"))); + pan_astyle_menu.items().push_back (MenuElem (_("abs"))); + + gain_astate_menu.set_name ("ArdourContextMenu"); + gain_astyle_menu.set_name ("ArdourContextMenu"); + pan_astate_menu.set_name ("ArdourContextMenu"); + pan_astyle_menu.set_name ("ArdourContextMenu"); + + ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_style_button, _("gain automation mode")); + ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_style_button, _("pan automation mode")); + ARDOUR_UI::instance()->tooltips().set_tip (gain_automation_state_button, _("gain automation state")); + ARDOUR_UI::instance()->tooltips().set_tip (pan_automation_state_button, _("pan automation state")); + + if (is_audio_track()) { + + AudioTrack* at = dynamic_cast(&_route); + + at->FreezeChange.connect (slot (*this, &MixerStrip::map_frozen)); + + speed_adjustment.value_changed.connect (slot (*this, &MixerStrip::speed_adjustment_changed)); + + speed_frame.set_name ("BaseFrame"); + speed_frame.set_shadow_type (GTK_SHADOW_IN); + speed_frame.add (speed_spinner); + + speed_spinner.set_print_func (speed_printer, 0); + + ARDOUR_UI::instance()->tooltips().set_tip (speed_spinner, _("varispeed")); + + speed_spinner.show (); + speed_frame.show (); + + button_table.attach (speed_frame, 0, 2, 6, 7); + button_table.attach (*rec_enable_button, 0, 2, 7, 8); + } + + name_button.add (name_label); + name_button.set_name ("MixerNameButton"); + Gtkmmext::set_usize_to_display_given_text (name_button, "longest label", 2, 2); + + name_label.set_name ("MixerNameButtonLabel"); + name_label.set_text (_route.name()); + + group_button.add (group_label); + group_button.set_name ("MixerGroupButton"); + group_label.set_name ("MixerGroupButtonLabel"); + + comment_button.set_name ("MixerCommentButton"); + ARDOUR_UI::instance()->tooltips().set_tip (comment_button, _route.comment()=="" ? + _("click to add/edit comments"): + _route.comment()); + comment_button.clicked.connect (slot (*this, &MixerStrip::comment_button_clicked)); + + global_vpacker.set_border_width (4); + global_vpacker.set_spacing (4); + + Gtk::VBox *whvbox = manage (new Gtk::VBox); + + width_button.set_name ("MixerWidthButton"); + hide_button.set_name ("MixerHideButton"); + + width_button.clicked.connect (slot (*this, &MixerStrip::width_clicked)); + hide_button.clicked.connect (slot (*this, &MixerStrip::hide_clicked)); + + width_hide_box.pack_start (width_button, false, true); + width_hide_box.pack_end (hide_button, false, true); + + whvbox->pack_start (width_hide_box, true, true); + + global_vpacker.pack_start (*whvbox, false, false); + global_vpacker.pack_start (button_table, false, false); + global_vpacker.pack_start (pre_redirect_box, true, true); + global_vpacker.pack_start (gpm, false, false); + global_vpacker.pack_start (post_redirect_box, true, true); + global_vpacker.pack_start (panners, false, false); + global_vpacker.pack_start (output_button, false, false); + global_vpacker.pack_start (comment_button, false, false); + + global_frame.add (global_vpacker); + global_frame.set_shadow_type (GTK_SHADOW_IN); + global_frame.set_name ("BaseFrame"); + + add (global_frame); + + /* force setting of visible selected status */ + + _selected = true; + set_selected (false); + + whvbox->show_all (); + name_label.show (); + group_label.show(); + input_label.show (); + output_label.show (); + pre_redirect_box.show_all (); + post_redirect_box.show_all (); + button_table.show (); + comment_button.show (); + name_button.show (); + input_button.show (); + group_button.show (); + output_button.show (); + rec_enable_button->show (); + solo_button->show (); + mute_button->show (); + gain_automation_style_button.show (); + gain_automation_state_button.show (); + pan_automation_style_button.show (); + pan_automation_state_button.show (); + polarity_button.show (); + global_vpacker.show (); + global_frame.show (); + + _packed = false; + _embedded = false; + + _route.input_changed.connect (slot (*this, &MixerStrip::input_changed)); + _route.output_changed.connect (slot (*this, &MixerStrip::output_changed)); + _route.mute_changed.connect (slot (*this, &RouteUI::mute_changed)); + _route.solo_changed.connect (slot (*this, &RouteUI::solo_changed)); + _route.solo_safe_changed.connect (slot (*this, &RouteUI::solo_changed)); + _route.mix_group_changed.connect (slot (*this, &MixerStrip::mix_group_changed)); + _route.gain_automation_curve().automation_state_changed.connect (slot (*this, &MixerStrip::gain_automation_state_changed)); + _route.gain_automation_curve().automation_style_changed.connect (slot (*this, &MixerStrip::gain_automation_style_changed)); + _route.panner().Changed.connect (slot (*this, &MixerStrip::connect_to_pan)); + + if (is_audio_track()) { + audio_track()->diskstream_changed.connect (slot (*this, &MixerStrip::diskstream_changed)); + get_diskstream()->speed_changed.connect (slot (*this, &MixerStrip::speed_changed)); + } + + _route.name_changed.connect (slot (*this, &RouteUI::name_changed)); + _route.comment_changed.connect (slot (*this, &MixerStrip::comment_changed)); + _route.gui_changed.connect (slot (*this, &MixerStrip::route_gui_changed)); + + input_button.button_release_event.connect (slot (*this, &MixerStrip::input_press)); + output_button.button_release_event.connect (slot (*this, &MixerStrip::output_press)); + + rec_enable_button->button_press_event.connect (slot (*this, &RouteUI::rec_enable_press)); + solo_button->button_press_event.connect (slot (*this, &RouteUI::solo_press)); + solo_button->button_release_event.connect (slot (*this, &RouteUI::solo_release)); + mute_button->button_press_event.connect (slot (*this, &RouteUI::mute_press)); + mute_button->button_release_event.connect (slot (*this, &RouteUI::mute_release)); + + gain_automation_style_button.button_press_event.connect_after (slot (do_not_propagate)); + pan_automation_style_button.button_press_event.connect_after (slot (do_not_propagate)); + gain_automation_state_button.button_press_event.connect_after (slot (do_not_propagate)); + pan_automation_state_button.button_press_event.connect_after (slot (do_not_propagate)); + + gain_automation_style_button.button_press_event.connect (slot (*this, &MixerStrip::gain_automation_style_button_event)); + gain_automation_style_button.button_release_event.connect (slot (*this, &MixerStrip::gain_automation_style_button_event)); + pan_automation_style_button.button_press_event.connect (slot (*this, &MixerStrip::pan_automation_style_button_event)); + pan_automation_style_button.button_release_event.connect (slot (*this, &MixerStrip::pan_automation_style_button_event)); + + gain_automation_state_button.button_press_event.connect (slot (*this, &MixerStrip::gain_automation_state_button_event)); + gain_automation_state_button.button_release_event.connect (slot (*this, &MixerStrip::gain_automation_state_button_event)); + pan_automation_state_button.button_press_event.connect (slot (*this, &MixerStrip::pan_automation_state_button_event)); + pan_automation_state_button.button_release_event.connect (slot (*this, &MixerStrip::pan_automation_state_button_event)); + + polarity_button.toggled.connect (slot (*this, &MixerStrip::polarity_toggled)); + + name_button.button_release_event.connect (slot (*this, &MixerStrip::name_button_button_release)); + + group_button.button_press_event.connect (slot (*this, &MixerStrip::select_mix_group)); + + _width = (Width) -1; + set_stuff_from_route (); + + /* start off as a passthru strip. we'll correct this, if necessary, + in update_diskstream_display(). + */ + + set_name ("AudioTrackStripBase"); + + /* now force an update of all the various elements */ + + pre_redirect_box.update(); + post_redirect_box.update(); + mute_changed (0); + solo_changed (0); + name_changed (0); + comment_changed (0); + mix_group_changed (0); + gain_automation_state_changed (); + pan_automation_state_changed (); + connect_to_pan (); + + panners.setup_pan (); + + if (is_audio_track()) { + speed_changed (); + } + + /* XXX hack: no phase invert changed signal */ + + polarity_button.set_active (_route.phase_invert()); + + update_diskstream_display (); + update_input_display (); + update_output_display (); + + add_events (GDK_BUTTON_RELEASE_MASK); +} + +MixerStrip::~MixerStrip () +{ + GoingAway(); /* EMIT_SIGNAL */ + + if (input_selector) { + delete input_selector; + } + + if (output_selector) { + delete output_selector; + } +} + +void +MixerStrip::set_stuff_from_route () +{ + XMLProperty *prop; + + ensure_xml_node (); + + if ((prop = xml_node->property ("strip_width")) != 0) { + if (prop->value() == "wide") { + set_width (Wide); + } else if (prop->value() == "narrow") { + set_width (Narrow); + } + else { + error << compose(_("unknown strip width \"%1\" in XML GUI information"), prop->value()) << endmsg; + set_width (Wide); + } + } + else { + set_width (Wide); + } + + if ((prop = xml_node->property ("shown_mixer")) != 0) { + if (prop->value() == "no") { + _marked_for_display = false; + } else { + _marked_for_display = true; + } + } + else { + /* backwards compatibility */ + _marked_for_display = true; + } +} + +void +MixerStrip::set_width (Width w) +{ + /* always set the gpm width again, things may be hidden */ + gpm.set_width (w); + panners.set_width (w); + pre_redirect_box.set_width (w); + post_redirect_box.set_width (w); + + if (_width == w) { + return; + } + + ensure_xml_node (); + + _width = w; + + switch (w) { + case Wide: + set_usize (-1, -1); + xml_node->add_property ("strip_width", "wide"); + + static_cast (rec_enable_button->get_child())->set_text (_("RECORD")); + static_cast (mute_button->get_child())->set_text (_("mute")); + static_cast (solo_button->get_child())->set_text (_("solo")); + static_cast (comment_button.get_child())->set_text (_("comments")); + static_cast (gain_automation_style_button.get_child())->set_text (astyle_string(_route.gain_automation_curve().automation_style())); + static_cast (gain_automation_state_button.get_child())->set_text (astate_string(_route.gain_automation_curve().automation_state())); + static_cast (pan_automation_style_button.get_child())->set_text (astyle_string(_route.panner().automation_style())); + static_cast (pan_automation_state_button.get_child())->set_text (astate_string(_route.panner().automation_state())); + static_cast (polarity_button.get_child())->set_text (_("polarity")); + Gtkmmext::set_usize_to_display_given_text (name_button, "long", 2, 2); + break; + + case Narrow: + set_usize (50, -1); + xml_node->add_property ("strip_width", "narrow"); + + static_cast (rec_enable_button->get_child())->set_text (_("REC")); + static_cast (mute_button->get_child())->set_text (_("m")); + static_cast (solo_button->get_child())->set_text (_("s")); + static_cast (comment_button.get_child())->set_text (_("cmt")); + static_cast (gain_automation_style_button.get_child())->set_text (short_astyle_string(_route.gain_automation_curve().automation_style())); + static_cast (gain_automation_state_button.get_child())->set_text (short_astate_string(_route.gain_automation_curve().automation_state())); + static_cast (pan_automation_style_button.get_child())->set_text (short_astyle_string(_route.panner().automation_style())); + static_cast (pan_automation_state_button.get_child())->set_text (short_astate_string(_route.panner().automation_state())); + static_cast (polarity_button.get_child())->set_text (_("pol")); + Gtkmmext::set_usize_to_display_given_text (name_button, "longest label", 2, 2); + break; + } + + update_input_display (); + update_output_display (); + mix_group_changed (0); + name_changed (0); +} + +void +MixerStrip::set_packed (bool yn) +{ + _packed = yn; + + ensure_xml_node (); + + if (_packed) { + xml_node->add_property ("shown_mixer", "yes"); + } else { + xml_node->add_property ("shown_mixer", "no"); + } +} + + +gint +MixerStrip::output_press (GdkEventButton *ev) +{ + using namespace Menu_Helpers; + + if (!_session.engine().connected()) { + ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible")); + return TRUE; + } + + MenuList& citems = output_menu.items(); + output_menu.set_name ("ArdourContextMenu"); + citems.clear(); + + citems.push_back (MenuElem (_("Edit"), slot (*this, &MixerStrip::edit_output_configuration))); + citems.push_back (SeparatorElem()); + citems.push_back (MenuElem (_("Disconnect"), slot (*(static_cast(this)), &RouteUI::disconnect_output))); + citems.push_back (SeparatorElem()); + + _session.foreach_connection (this, &MixerStrip::add_connection_to_output_menu); + + output_menu.popup (1, ev->time); + + return TRUE; +} + +void +MixerStrip::edit_output_configuration () +{ + if (output_selector == 0) { + output_selector = new IOSelectorWindow (_session, _route, false); + } + + if (output_selector->is_visible()) { + output_selector->get_toplevel()->get_window().raise(); + } else { + output_selector->show_all (); + } +} + +void +MixerStrip::edit_input_configuration () +{ + if (input_selector == 0) { + input_selector = new IOSelectorWindow (_session, _route, true); + } + + if (input_selector->is_visible()) { + input_selector->get_toplevel()->get_window().raise(); + } else { + input_selector->show_all (); + } +} + +gint +MixerStrip::input_press (GdkEventButton *ev) +{ + using namespace Menu_Helpers; + + MenuList& citems = input_menu.items(); + input_menu.set_name ("ArdourContextMenu"); + citems.clear(); + + if (!_session.engine().connected()) { + ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible")); + return TRUE; + } + +#if ADVANCED_ROUTE_DISKSTREAM_CONNECTIVITY + if (is_audio_track()) { + citems.push_back (MenuElem (_("Track"), slot (*this, &MixerStrip::select_stream_input))); + } +#endif + citems.push_back (MenuElem (_("Edit"), slot (*this, &MixerStrip::edit_input_configuration))); + citems.push_back (SeparatorElem()); + citems.push_back (MenuElem (_("Disconnect"), slot (*(static_cast(this)), &RouteUI::disconnect_input))); + citems.push_back (SeparatorElem()); + + _session.foreach_connection (this, &MixerStrip::add_connection_to_input_menu); + + input_menu.popup (1, ev->time); + + return TRUE; +} + +void +MixerStrip::connection_input_chosen (ARDOUR::Connection *c) +{ + if (!ignore_toggle) { + + try { + _route.use_input_connection (*c, this); + } + + catch (AudioEngine::PortRegistrationFailure& err) { + error << _("could not register new ports required for that connection") + << endmsg; + } + } +} + +void +MixerStrip::connection_output_chosen (ARDOUR::Connection *c) +{ + if (!ignore_toggle) { + + try { + _route.use_output_connection (*c, this); + } + + catch (AudioEngine::PortRegistrationFailure& err) { + error << _("could not register new ports required for that connection") + << endmsg; + } + } +} + +void +MixerStrip::add_connection_to_input_menu (ARDOUR::Connection* c) +{ + using namespace Menu_Helpers; + + if (dynamic_cast (c) == 0) { + return; + } + + MenuList& citems = input_menu.items(); + + if (c->nports() == _route.n_inputs()) { + + citems.push_back (CheckMenuElem (c->name(), bind (slot (*this, &MixerStrip::connection_input_chosen), c))); + + ARDOUR::Connection *current = _route.input_connection(); + + if (current == c) { + ignore_toggle = true; + dynamic_cast (citems.back())->set_active (true); + ignore_toggle = false; + } + } +} + +void +MixerStrip::add_connection_to_output_menu (ARDOUR::Connection* c) +{ + using namespace Menu_Helpers; + + if (dynamic_cast (c) == 0) { + return; + } + + if (c->nports() == _route.n_outputs()) { + + MenuList& citems = output_menu.items(); + citems.push_back (CheckMenuElem (c->name(), bind (slot (*this, &MixerStrip::connection_output_chosen), c))); + + ARDOUR::Connection *current = _route.output_connection(); + + if (current == c) { + ignore_toggle = true; + dynamic_cast (citems.back())->set_active (true); + ignore_toggle = false; + } + } +} + +void +MixerStrip::select_stream_input () +{ + using namespace Menu_Helpers; + + Menu *stream_menu = manage (new Menu); + MenuList& items = stream_menu->items(); + stream_menu->set_name ("ArdourContextMenu"); + + Session::DiskStreamList streams = _session.disk_streams(); + + for (Session::DiskStreamList::iterator i = streams.begin(); i != streams.end(); ++i) { + + if (!(*i)->hidden()) { + + items.push_back (CheckMenuElem ((*i)->name(), bind (slot (*this, &MixerStrip::stream_input_chosen), *i))); + + if (get_diskstream() == *i) { + ignore_toggle = true; + static_cast (items.back())->set_active (true); + ignore_toggle = false; + } + } + } + + stream_menu->popup (1, 0); +} + +void +MixerStrip::stream_input_chosen (DiskStream *stream) +{ + if (is_audio_track()) { + audio_track()->set_diskstream (*stream, this); + } +} + +void +MixerStrip::update_diskstream_display () +{ + if (is_audio_track()) { + + map_frozen (); + + update_input_display (); + + if (input_selector) { + input_selector->hide_all (); + } + + show_route_color (); + + } else { + + map_frozen (); + + update_input_display (); + show_passthru_color (); + } +} + +void +MixerStrip::connect_to_pan () +{ + ENSURE_GUI_THREAD(slot (*this, &MixerStrip::connect_to_pan)); + + panstate_connection.disconnect (); + panstyle_connection.disconnect (); + + if (!_route.panner().empty()) { + StreamPanner* sp = _route.panner().front(); + + panstate_connection = sp->automation().automation_state_changed.connect (slot (*this, &MixerStrip::pan_automation_state_changed)); + panstyle_connection = sp->automation().automation_style_changed.connect (slot (*this, &MixerStrip::pan_automation_style_changed)); + } + + panners.pan_changed (this); +} + +void +MixerStrip::update_input_display () +{ + ARDOUR::Connection *c; + + if ((c = _route.input_connection()) != 0) { + input_label.set_text (c->name()); + } else { + switch (_width) { + case Wide: + input_label.set_text (_("INPUT")); + break; + case Narrow: + input_label.set_text (_("IN")); + break; + } + } + + panners.setup_pan (); +} + +void +MixerStrip::update_output_display () +{ + ARDOUR::Connection *c; + + if ((c = _route.output_connection()) != 0) { + output_label.set_text (c->name()); + } else { + switch (_width) { + case Wide: + output_label.set_text (_("OUTPUT")); + break; + case Narrow: + output_label.set_text (_("OUT")); + break; + } + } + + gpm.setup_meters (); + panners.setup_pan (); +} + +void +MixerStrip::update () +{ + gpm.update_meters (); +} + +void +MixerStrip::fast_update () +{ + if (_session.meter_falloff() > 0.0f) { + gpm.update_meters_falloff (); + } +} + +gint +MixerStrip::gain_automation_state_button_event (GdkEventButton *ev) +{ + if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) { + return TRUE; + } + + switch (ev->button) { + case 1: + switch (ev->button) { + case 1: + gain_astate_menu.popup (1, ev->time); + break; + default: + break; + } + } + + return TRUE; +} + +gint +MixerStrip::gain_automation_style_button_event (GdkEventButton *ev) +{ + if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) { + return TRUE; + } + + switch (ev->button) { + case 1: + gain_astyle_menu.popup (1, ev->time); + break; + default: + break; + } + return TRUE; +} + +gint +MixerStrip::pan_automation_state_button_event (GdkEventButton *ev) +{ + using namespace Menu_Helpers; + + if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) { + return TRUE; + } + + switch (ev->button) { + case 1: + pan_astate_menu.popup (1, ev->time); + break; + default: + break; + } + + return TRUE; +} + +gint +MixerStrip::pan_automation_style_button_event (GdkEventButton *ev) +{ + switch (ev->button) { + case 1: + pan_astyle_menu.popup (1, ev->time); + break; + default: + break; + } + return TRUE; +} + +string +MixerStrip::astate_string (AutoState state) +{ + return _astate_string (state, false); +} + +string +MixerStrip::short_astate_string (AutoState state) +{ + return _astate_string (state, true); +} + +string +MixerStrip::_astate_string (AutoState state, bool shrt) +{ + string sstr; + + switch (state) { + case Off: + sstr = (shrt ? "--" : _("off")); + break; + case Play: + sstr = (shrt ? "P" : _("aplay")); + break; + case Touch: + sstr = (shrt ? "T" : _("touch")); + break; + case Write: + sstr = (shrt ? "W" : _("awrite")); + break; + } + + return sstr; +} + +string +MixerStrip::astyle_string (AutoStyle style) +{ + return _astyle_string (style, false); +} + +string +MixerStrip::short_astyle_string (AutoStyle style) +{ + return _astyle_string (style, true); +} + +string +MixerStrip::_astyle_string (AutoStyle style, bool shrt) +{ + if (style & Trim) { + return _("trim"); + } else { + /* XXX it might different in different languages */ + + return (shrt ? _("abs") : _("abs")); + } +} + +void +MixerStrip::diskstream_changed (void *src) +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &MixerStrip::update_diskstream_display)); +} + +void +MixerStrip::gain_automation_style_changed () +{ + switch (_width) { + case Wide: + static_cast (gain_automation_style_button.get_child())->set_text (astyle_string(_route.gain_automation_curve().automation_style())); + break; + case Narrow: + static_cast (gain_automation_style_button.get_child())->set_text (short_astyle_string(_route.gain_automation_curve().automation_style())); + break; + } +} + +void +MixerStrip::gain_automation_state_changed () +{ + ENSURE_GUI_THREAD(slot (*this, &MixerStrip::gain_automation_state_changed)); + + bool x; + + switch (_width) { + case Wide: + static_cast (gain_automation_state_button.get_child())->set_text (astate_string(_route.gain_automation_curve().automation_state())); + break; + case Narrow: + static_cast (gain_automation_state_button.get_child())->set_text (short_astate_string(_route.gain_automation_curve().automation_state())); + break; + } + + x = (_route.gain_automation_state() != Off); + + if (gain_automation_state_button.get_active() != x) { + ignore_toggle = true; + gain_automation_state_button.set_active (x); + ignore_toggle = false; + } + + gpm.update_gain_sensitive (); + + /* start watching automation so that things move */ + + gain_watching.disconnect(); + + if (x) { + gain_watching = ARDOUR_UI::RapidScreenUpdate.connect (slot (gpm, &GainMeter::effective_gain_display)); + } +} + +void +MixerStrip::pan_automation_style_changed () +{ + ENSURE_GUI_THREAD(slot (*this, &MixerStrip::pan_automation_style_changed)); + + switch (_width) { + case Wide: + static_cast (pan_automation_style_button.get_child())->set_text (astyle_string(_route.panner().automation_style())); + break; + case Narrow: + static_cast (pan_automation_style_button.get_child())->set_text (short_astyle_string(_route.panner().automation_style())); + break; + } +} + +void +MixerStrip::pan_automation_state_changed () +{ + ENSURE_GUI_THREAD(slot (*this, &MixerStrip::pan_automation_state_changed)); + + bool x; + + switch (_width) { + case Wide: + static_cast (pan_automation_state_button.get_child())->set_text (astate_string(_route.panner().automation_state())); + break; + case Narrow: + static_cast (pan_automation_state_button.get_child())->set_text (short_astate_string(_route.panner().automation_state())); + break; + } + + /* when creating a new session, we get to create busses (and + sometimes tracks) with no outputs by the time they get + here. + */ + + if (_route.panner().empty()) { + return; + } + + x = (_route.panner().front()->automation().automation_state() != Off); + + if (pan_automation_state_button.get_active() != x) { + ignore_toggle = true; + pan_automation_state_button.set_active (x); + ignore_toggle = false; + } + + panners.update_pan_sensitive (); + + /* start watching automation so that things move */ + + pan_watching.disconnect(); + + if (x) { + pan_watching = ARDOUR_UI::RapidScreenUpdate.connect (slot (panners, &PannerUI::effective_pan_display)); + } +} + +void +MixerStrip::input_changed (IOChange change, void *src) +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &MixerStrip::update_input_display)); +} + +void +MixerStrip::output_changed (IOChange change, void *src) +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &MixerStrip::update_output_display)); +} + +void +MixerStrip::comment_button_clicked () +{ + if (comment_window == 0) { + setup_comment_editor (); + } + + if (comment_window->is_visible()) { + comment_window->hide (); + } else { + comment_window->set_position (GTK_WIN_POS_MOUSE); + comment_window->show_all (); + } +} + +void +MixerStrip::setup_comment_editor () +{ + comment_window = new Window (GTK_WINDOW_TOPLEVEL); + + string str; + str = _route.name(); + str += _(": comment editor"); + comment_window->set_title (str); + + comment_area.set_name ("MixerTrackCommentArea"); + comment_area.set_editable (true); + comment_area.focus_in_event.connect (slot (ARDOUR_UI::generic_focus_in_event)); + comment_area.focus_out_event.connect (slot (ARDOUR_UI::generic_focus_out_event)); + comment_area.changed.connect (slot (*this, &MixerStrip::comment_edited)); + comment_area.button_release_event.connect_after (slot (do_not_propagate)); + comment_area.show (); + + comment_window->add (comment_area); + comment_window->delete_event.connect (bind (slot (just_hide_it), comment_window)); +} + +void +MixerStrip::comment_changed (void *src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &MixerStrip::comment_changed), src)); + + if (src != this) { + ignore_comment_edit = true; + comment_area.freeze (); + comment_area.delete_text (0, -1); + comment_area.set_point (0); + comment_area.insert (_route.comment()); + comment_area.thaw (); + ignore_comment_edit = false; + } +} + +void +MixerStrip::comment_edited () +{ + ENSURE_GUI_THREAD(slot (*this, &MixerStrip::comment_edited)); + + if (!ignore_comment_edit) { + string str = comment_area.get_chars(0,-1); + _route.set_comment (str, this); + ARDOUR_UI::instance()->tooltips().set_tip (comment_button, + str.empty() ? _("click to add/edit comments") : str); + } +} + +void +MixerStrip::set_mix_group (RouteGroup *rg) + +{ + _route.set_mix_group (rg, this); + delete group_menu; + group_menu = 0; +} + +void +MixerStrip::add_mix_group_to_menu (RouteGroup *rg) +{ + using namespace Menu_Helpers; + + MenuList& items = group_menu->items(); + items.push_back (MenuElem (rg->name(), bind (slot (*this, &MixerStrip::set_mix_group), rg))); +} + +gint +MixerStrip::select_mix_group (GdkEventButton *ev) +{ + using namespace Menu_Helpers; + + group_menu = new Menu; + group_menu->set_name ("ArdourContextMenu"); + MenuList& items = group_menu->items(); + + items.push_back (MenuElem (_("no group"), bind (slot (*this, &MixerStrip::set_mix_group), (RouteGroup *) 0))); + _session.foreach_mix_group (this, &MixerStrip::add_mix_group_to_menu); + + group_menu->popup (ev->button, 0); + return stop_signal (group_button, "button_press_event"); +} + +void +MixerStrip::mix_group_changed (void *ignored) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &MixerStrip::mix_group_changed), ignored)); + + RouteGroup *rg = _route.mix_group(); + + if (rg) { + group_label.set_text (rg->name()); + } else { + switch (_width) { + case Wide: + group_label.set_text (_("no group")); + break; + case Narrow: + group_label.set_text (_("~G")); + break; + } + } +} + +void +MixerStrip::polarity_toggled () +{ + bool x; + + if ((x = polarity_button.get_active()) != _route.phase_invert()) { + _route.set_phase_invert (x, this); + } +} + + +void +MixerStrip::route_gui_changed (string what_changed, void* ignored) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &MixerStrip::route_gui_changed), what_changed, ignored)); + + if (what_changed == "color") { + if (set_color_from_route () == 0) { + show_route_color (); + } + } +} + +void +MixerStrip::show_route_color () +{ + Gtk::Style *style; + + name_button.ensure_style (); + style = name_button.get_style()->copy(); + style->set_bg (GTK_STATE_NORMAL, color()); + name_button.set_style (*style); + style->unref(); + + route_active_changed (); +} + +void +MixerStrip::show_passthru_color () +{ + route_active_changed (); +} + +void +MixerStrip::build_route_ops_menu () +{ + using namespace Menu_Helpers; + + route_ops_menu = new Menu; + route_ops_menu->set_name ("ArdourContextMenu"); + + MenuList& items = route_ops_menu->items(); + + items.push_back (MenuElem (_("Rename"), slot (*this, &RouteUI::route_rename))); + items.push_back (SeparatorElem()); + items.push_back (CheckMenuElem (_("Active"), slot (*this, &RouteUI::toggle_route_active))); + route_active_menu_item = dynamic_cast (items.back()); + route_active_menu_item->set_active (_route.active()); + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Remove"), slot (*this, &RouteUI::remove_this_route))); +} + +gint +MixerStrip::name_button_button_release (GdkEventButton* ev) +{ + if (ev->button == 3) { + list_route_operations (); + } + return FALSE; +} + +void +MixerStrip::list_route_operations () +{ + if (route_ops_menu == 0) { + build_route_ops_menu (); + } + + route_ops_menu->popup (1, 0); +} + + +void +MixerStrip::speed_adjustment_changed () +{ + /* since there is a usable speed adjustment, there has to be a diskstream */ + if (!ignore_speed_adjustment) { + get_diskstream()->set_speed (speed_adjustment.get_value()); + } +} + +void +MixerStrip::speed_changed () +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &MixerStrip::update_speed_display)); +} + +void +MixerStrip::update_speed_display () +{ + float val; + + val = get_diskstream()->speed(); + + if (val != 1.0) { + speed_spinner.set_name ("MixerStripSpeedBaseNotOne"); + } else { + speed_spinner.set_name ("MixerStripSpeedBase"); + } + + if (speed_adjustment.get_value() != val) { + ignore_speed_adjustment = true; + speed_adjustment.set_value (val); + ignore_speed_adjustment = false; + } +} + + +void +MixerStrip::set_selected (bool yn) +{ + AxisView::set_selected (yn); + if (_selected) { + global_frame.set_shadow_type (GTK_SHADOW_ETCHED_OUT); + global_frame.set_name ("MixerStripSelectedFrame"); + } else { + global_frame.set_shadow_type (GTK_SHADOW_IN); + global_frame.set_name ("MixerStripFrame"); + } + global_frame.queue_draw (); +} + +void +MixerStrip::name_changed (void *src) +{ + switch (_width) { + case Wide: + RouteUI::name_changed (src); + break; + case Narrow: + name_label.set_text (short_version (_route.name(), 5)); + break; + } +} + +void +MixerStrip::width_clicked () +{ + switch (_width) { + case Wide: + set_width (Narrow); + break; + case Narrow: + set_width (Wide); + break; + } +} + +void +MixerStrip::hide_clicked () +{ + if (_embedded) { + Hiding(); /* EMIT_SIGNAL */ + } else { + _mixer.unselect_strip_in_display (this); + } +} + +void +MixerStrip::set_embedded (bool yn) +{ + _embedded = yn; +} + +void +MixerStrip::map_frozen () +{ + ENSURE_GUI_THREAD (slot (*this, &MixerStrip::map_frozen)); + + AudioTrack* at = dynamic_cast(&_route); + + if (at) { + switch (at->freeze_state()) { + case AudioTrack::Frozen: + pre_redirect_box.set_sensitive (false); + post_redirect_box.set_sensitive (false); + speed_spinner.set_sensitive (false); + break; + default: + pre_redirect_box.set_sensitive (true); + post_redirect_box.set_sensitive (true); + speed_spinner.set_sensitive (true); + break; + } + } + _route.foreach_redirect (this, &MixerStrip::hide_redirect_editor); +} + +void +MixerStrip::hide_redirect_editor (Redirect* redirect) +{ + void* gui = redirect->get_gui (); + + if (gui) { + static_cast(gui)->hide (); + } +} + +void +MixerStrip::route_active_changed () +{ + RouteUI::route_active_changed (); + + if (is_audio_track()) { + if (_route.active()) { + set_name ("AudioTrackStripBase"); + gpm.set_meter_strip_name ("AudioTrackStripBase"); + } else { + set_name ("AudioTrackStripBaseInactive"); + gpm.set_meter_strip_name ("AudioTrackStripBaseInactive"); + } + gpm.set_fader_name ("AudioTrackFader"); + } else { + if (_route.active()) { + set_name ("AudioBusStripBase"); + gpm.set_meter_strip_name ("AudioBusStripBase"); + } else { + set_name ("AudioBusStripBaseInactive"); + gpm.set_meter_strip_name ("AudioBusStripBaseInactive"); + } + gpm.set_fader_name ("AudioBusFader"); + } +} diff --git a/gtk2_ardour/mixer_strip.h b/gtk2_ardour/mixer_strip.h new file mode 100644 index 0000000000..055fa7a6bb --- /dev/null +++ b/gtk2_ardour/mixer_strip.h @@ -0,0 +1,257 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_mixer_strip__ +#define __ardour_mixer_strip__ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "route_ui.h" +#include "io_selector.h" +#include "gain_meter.h" +#include "panner_ui.h" +#include "enums.h" +#include "redirect_box.h" + +class MotionController; + + +namespace Gtkmmext { + class SliderController; +} + +namespace ARDOUR { + class Route; + class Send; + class Insert; + class Session; + class PortInsert; + class Connection; + class Plugin; +} + +class Mixer_UI; + +class MixerStrip : public RouteUI, public Gtk::EventBox +{ + public: + MixerStrip (Mixer_UI&, ARDOUR::Session&, ARDOUR::Route &, bool in_mixer = true); + ~MixerStrip (); + + void set_width (Width); + Width get_width() const { return _width; } + + void update (); + void fast_update (); + void set_embedded (bool); + + protected: + friend class Mixer_UI; + void set_packed (bool yn); + bool packed () { return _packed; } + + void set_selected(bool yn); + void set_stuff_from_route (); + + private: + Mixer_UI& _mixer; + + bool _embedded; + bool _packed; + Width _width; + + Gtk::Button hide_button; + Gtk::Button width_button; + Gtk::HBox width_hide_box; + + void hide_clicked(); + void width_clicked (); + + Gtk::Frame global_frame; + Gtk::VBox global_vpacker; + + RedirectBox pre_redirect_box; + RedirectBox post_redirect_box; + GainMeter gpm; + PannerUI panners; + + Gtk::Table button_table; + + Gtk::Button diskstream_button; + Gtk::Label diskstream_label; + + Gtk::Button input_button; + Gtk::Label input_label; + Gtk::Button output_button; + Gtk::Label output_label; + + Gtk::Button gain_automation_style_button; + Gtk::ToggleButton gain_automation_state_button; + + Gtk::Button pan_automation_style_button; + Gtk::ToggleButton pan_automation_state_button; + + Gtk::Menu gain_astate_menu; + Gtk::Menu gain_astyle_menu; + Gtk::Menu pan_astate_menu; + Gtk::Menu pan_astyle_menu; + + Gtk::ToggleButton polarity_button; + + SigC::Connection newplug_connection; + + gint mark_update_safe (); + guint32 mode_switch_in_progress; + + Gtk::Button name_button; + + Gtk::Window* comment_window; + Gtk::Text comment_area; + Gtk::Button comment_button; + + void setup_comment_editor (); + void comment_button_clicked (); + + Gtk::Button group_button; + Gtk::Label group_label; + Gtk::Menu *group_menu; + + gint input_press (GdkEventButton *); + gint output_press (GdkEventButton *); + + Gtk::Menu input_menu; + void add_connection_to_input_menu (ARDOUR::Connection *); + + Gtk::Menu output_menu; + void add_connection_to_output_menu (ARDOUR::Connection *); + + void stream_input_chosen (ARDOUR::DiskStream*); + void select_stream_input (); + void connection_input_chosen (ARDOUR::Connection *); + void connection_output_chosen (ARDOUR::Connection *); + + void edit_input_configuration (); + void edit_output_configuration (); + + void diskstream_changed (void *src); + + Gtk::Menu *send_action_menu; + void build_send_action_menu (); + + void new_send (); + void show_send_controls (); + + + gint gain_automation_style_button_event (GdkEventButton *); + gint gain_automation_state_button_event (GdkEventButton *); + gint pan_automation_style_button_event (GdkEventButton *); + gint pan_automation_state_button_event (GdkEventButton *); + + void input_changed (ARDOUR::IOChange, void *); + void output_changed (ARDOUR::IOChange, void *); + void gain_automation_state_changed(); + void pan_automation_state_changed(); + void gain_automation_style_changed(); + void pan_automation_style_changed(); + + SigC::Connection panstate_connection; + SigC::Connection panstyle_connection; + void connect_to_pan (); + + std::string astate_string (ARDOUR::AutoState); + std::string short_astate_string (ARDOUR::AutoState); + std::string _astate_string (ARDOUR::AutoState, bool); + + std::string astyle_string (ARDOUR::AutoStyle); + std::string short_astyle_string (ARDOUR::AutoStyle); + std::string _astyle_string (ARDOUR::AutoStyle, bool); + + void update_diskstream_display (); + void update_input_display (); + void update_output_display (); + + void set_automated_controls_sensitivity (bool yn); + + Gtk::Menu *route_ops_menu; + void build_route_ops_menu (); + gint name_button_button_release (GdkEventButton*); + void list_route_operations (); + + gint comment_key_release_handler (GdkEventKey*); + void comment_changed (void *src); + void comment_edited (); + bool ignore_comment_edit; + + void set_mix_group (ARDOUR::RouteGroup *); + void add_mix_group_to_menu (ARDOUR::RouteGroup *); + gint select_mix_group (GdkEventButton *); + void mix_group_changed (void *); + + void polarity_toggled (); + + IOSelectorWindow *input_selector; + IOSelectorWindow *output_selector; + + Gtk::Style *passthru_style; + + void route_gui_changed (string, void*); + void show_route_color (); + void show_passthru_color (); + + void route_active_changed (); + + /* speed control (for tracks only) */ + + Gtk::Adjustment speed_adjustment; + Gtkmmext::ClickBox speed_spinner; + Gtk::Label speed_label; + Gtk::Frame speed_frame; + + void speed_adjustment_changed (); + void speed_changed (); + void name_changed (void *src); + void update_speed_display (); + void map_frozen (); + void hide_redirect_editor (ARDOUR::Redirect* redirect); + + SigC::Connection gain_watching; + SigC::Connection pan_watching; + bool ignore_speed_adjustment; + + string solo_button_name () const { return "MixerSoloButton"; } + string safe_solo_button_name () const { return "MixerSafeSoloButton"; } +}; + +#endif /* __ardour_mixer_strip__ */ diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc new file mode 100644 index 0000000000..e9eae0b3e2 --- /dev/null +++ b/gtk2_ardour/mixer_ui.cc @@ -0,0 +1,1063 @@ +/* + Copyright (C) 2000-2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mixer_ui.h" +#include "mixer_strip.h" +#include "plugin_selector.h" +#include "ardour_ui.h" +#include "check_mark.h" +#include "prompter.h" +#include "utils.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; +using namespace Gtkmmext; +using namespace SigC; + +static const gchar* track_display_titles[] = { + N_("Strips"), + 0 +}; +static const gchar* snapshot_display_titles[] = { + N_("Snapshots"), + 0 +}; + +static const gchar* group_list_titles[] = { + N_("***"), + N_("Bar"), + 0 +}; + +GdkPixmap* Mixer_UI::check_pixmap = 0; +GdkBitmap* Mixer_UI::check_mask = 0; +GdkPixmap* Mixer_UI::empty_pixmap = 0; +GdkBitmap* Mixer_UI::empty_mask = 0; + + +Mixer_UI::Mixer_UI (AudioEngine& eng) + : Gtk::Window (GTK_WINDOW_TOPLEVEL), + KeyboardTarget (*this, "mixer"), + engine (eng), + track_display_list (internationalize (track_display_titles)), + group_list (internationalize (group_list_titles)), + snapshot_display (internationalize (snapshot_display_titles)) + +{ + _strip_width = Wide; + track_menu = 0; + + check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, + gtk_widget_get_colormap (GTK_WIDGET(group_list.gtkobj())), + &check_mask, NULL, (gchar **) check_xpm); + empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, + gtk_widget_get_colormap (GTK_WIDGET(group_list.gtkobj())), + &empty_mask, NULL, (gchar **) empty_xpm); + + XMLNode* node = ARDOUR_UI::instance()->mixer_settings(); + set_state (*node); + + scroller_base.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + scroller_base.set_name ("MixerWindow"); + scroller_base.button_release_event.connect (slot (*this, &Mixer_UI::strip_scroller_button_release)); + // add as last item of strip packer + strip_packer.pack_end (scroller_base, true, true); + + scroller.add_with_viewport (strip_packer); + scroller.set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + track_display_list.column_titles_active(); + track_display_list.set_name ("MixerTrackDisplayList"); + track_display_list.set_shadow_type (GTK_SHADOW_IN); + track_display_list.set_selection_mode (GTK_SELECTION_MULTIPLE); + track_display_list.set_reorderable (true); + track_display_list.set_usize (75, -1); + track_display_scroller.add (track_display_list); + track_display_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + snapshot_display.column_titles_active(); + snapshot_display.set_name ("MixerSnapshotDisplayList"); + snapshot_display.set_shadow_type (GTK_SHADOW_IN); + snapshot_display.set_selection_mode (GTK_SELECTION_SINGLE); + snapshot_display.set_reorderable (true); + snapshot_display.set_usize (75, -1); + snapshot_display_scroller.add (snapshot_display); + snapshot_display_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + group_list_button_label.set_text (_("Mix Groups")); + group_list_button_label.set_name ("MixerGroupTitleButton"); + group_list_button.add (group_list_button_label); + group_list_button.set_name ("MixerGroupTitleButton"); + + group_list.column_titles_hide(); + group_list.set_name ("MixerGroupList"); + group_list.set_shadow_type (GTK_SHADOW_IN); + group_list.set_selection_mode (GTK_SELECTION_MULTIPLE); + group_list.set_reorderable (false); + group_list.set_usize (75, -1); + group_list.set_column_auto_resize (0, true); + group_list_scroller.add (group_list); + group_list_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + group_list_vbox.pack_start (group_list_button, false, false); + group_list_vbox.pack_start (group_list_scroller, true, true); + + list stupid_list; + + stupid_list.push_back (""); + stupid_list.push_back (_("-all-")); + + group_list.rows().push_back (stupid_list); + group_list.rows().back().set_data (0); + group_list.rows().back().select(); + group_list.cell(0,0).set_pixmap (check_pixmap); + + track_display_frame.set_name("BaseFrame"); + track_display_frame.set_shadow_type (GTK_SHADOW_IN); + track_display_frame.add(track_display_scroller); + + group_list_frame.set_name ("BaseFrame"); + group_list_frame.set_shadow_type (GTK_SHADOW_IN); + group_list_frame.add (group_list_vbox); + + rhs_pane1.add1 (track_display_frame); + rhs_pane1.add2 (rhs_pane2); + + rhs_pane2.add1 (group_list_frame); + rhs_pane2.add2 (snapshot_display_scroller); + + list_vpacker.pack_start (rhs_pane1, true, true); + + global_hpacker.pack_start (scroller, true, true); + global_hpacker.pack_start (out_packer, false, false); + + list_hpane.add1(list_vpacker); + list_hpane.add2(global_hpacker); + + rhs_pane1.size_allocate.connect_after (bind (slot (*this, &Mixer_UI::pane_allocation_handler), + static_cast (&rhs_pane1))); + rhs_pane2.size_allocate.connect_after (bind (slot (*this, &Mixer_UI::pane_allocation_handler), + static_cast (&rhs_pane2))); + list_hpane.size_allocate.connect_after (bind (slot (*this, &Mixer_UI::pane_allocation_handler), + static_cast (&list_hpane))); + + + rhs_pane1.set_data ("collapse-direction", (gpointer) 0); + rhs_pane2.set_data ("collapse-direction", (gpointer) 0); + list_hpane.set_data ("collapse-direction", (gpointer) 1); + + rhs_pane1.button_release_event.connect (bind (slot (pane_handler), static_cast(&rhs_pane1))); + rhs_pane2.button_release_event.connect (bind (slot (pane_handler), static_cast(&rhs_pane2))); + list_hpane.button_release_event.connect (bind (slot (pane_handler), static_cast(&list_hpane))); + + global_vpacker.pack_start (list_hpane, true, true); + + add (global_vpacker); + set_name ("MixerWindow"); + set_title (_("ardour: mixer")); + set_wmclass (_("ardour_mixer"), "Ardour"); + + delete_event.connect (bind (slot (just_hide_it), + static_cast(this))); + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK); + + snapshot_display.select_row.connect (slot (*this, &Mixer_UI::snapshot_display_selected)); + + track_display_list.select_row.connect (slot (*this, &Mixer_UI::track_display_selected)); + track_display_list.unselect_row.connect (slot (*this, &Mixer_UI::track_display_unselected)); + track_display_list.row_move.connect (slot (*this, &Mixer_UI::queue_track_display_reordered)); + track_display_list.click_column.connect (slot (*this, &Mixer_UI::track_column_click)); + + group_list_button.clicked.connect (slot (*this, &Mixer_UI::group_list_button_clicked)); + group_list.button_press_event.connect (slot (*this, &Mixer_UI::group_list_button_press_event)); + group_list.select_row.connect (slot (*this, &Mixer_UI::group_selected)); + group_list.unselect_row.connect (slot (*this, &Mixer_UI::group_unselected)); + + _plugin_selector = new PluginSelector (PluginManager::the_manager()); + _plugin_selector->delete_event.connect (bind (slot (just_hide_it), + static_cast (_plugin_selector))); + + configure_event.connect (slot (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler)); + + _selection.RoutesChanged.connect (slot (*this, &Mixer_UI::follow_strip_selection)); +} + +Mixer_UI::~Mixer_UI () +{ +} + +void +Mixer_UI::ensure_float (Window& win) +{ + win.set_transient_for (*this); +} + +void +Mixer_UI::show_window () +{ + show_all (); + + /* now reset each strips width so the right widgets are shown */ + MixerStrip* ms; + CList_Helpers::RowList::iterator i; + + for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) { + ms = (MixerStrip *) i->get_data (); + ms->set_width (ms->get_width()); + } +} + +void +Mixer_UI::add_strip (Route* route) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Mixer_UI::add_strip), route)); + + MixerStrip* strip; + + if (route->hidden()) { + return; + } + + strip = new MixerStrip (*this, *session, *route); + strips.push_back (strip); + + strip->set_width (_strip_width); + show_strip (strip); + + const gchar* rowdata[1]; + rowdata[0] = route->name().c_str(); + + track_display_list.freeze (); + track_display_list.rows().push_back (rowdata); + track_display_list.rows().back().set_data (strip); + track_display_list.thaw (); + + if (strip->marked_for_display() || strip->packed()) { + track_display_list.rows().back().select (); + } + + route->name_changed.connect (bind (slot (*this, &Mixer_UI::strip_name_changed), strip)); + strip->GoingAway.connect (bind (slot (*this, &Mixer_UI::remove_strip), strip)); + + strip->button_release_event.connect (bind (slot (*this, &Mixer_UI::strip_button_release_event), strip)); + +// if (width() < gdk_screen_width()) { +// set_usize (width() + (_strip_width == Wide ? 75 : 50), height()); +// } +} + +void +Mixer_UI::remove_strip (MixerStrip* strip) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Mixer_UI::remove_strip), strip)); + + CList_Helpers::RowList::iterator ri; + list::iterator i; + + if ((i = find (strips.begin(), strips.end(), strip)) != strips.end()) { + strips.erase (i); + } + + for (ri = track_display_list.rows().begin(); ri != track_display_list.rows().end(); ++ri) { + if ((MixerStrip *) ri->get_data () == strip) { + track_display_list.rows().erase (ri); + break; + } + } +} + +void +Mixer_UI::follow_strip_selection () +{ + for (list::iterator i = strips.begin(); i != strips.end(); ++i) { + (*i)->set_selected (_selection.selected (&(*i)->route())); + } +} + +gint +Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip) +{ + if (ev->button == 1) { + + /* this allows the user to click on the strip to terminate comment + editing. XXX it needs improving so that we don't select the strip + at the same time. + */ + + ARDOUR_UI::instance()->allow_focus (false); + + if (_selection.selected (&strip->route())) { + _selection.remove (&strip->route()); + } else { + if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) { + _selection.add (&strip->route()); + } else { + _selection.set (&strip->route()); + } + } + } + + return TRUE; +} + +void +Mixer_UI::connect_to_session (Session* sess) +{ + session = sess; + + string wintitle = _("ardour: mixer: "); + wintitle += session->name(); + set_title (wintitle); + + track_display_list.freeze (); + track_display_list.clear (); + + session->foreach_route (this, &Mixer_UI::add_strip); + + track_display_list.thaw (); + + session->going_away.connect (slot (*this, &Mixer_UI::disconnect_from_session)); + session->RouteAdded.connect (slot (*this, &Mixer_UI::add_strip)); + session->mix_group_added.connect (slot (*this, &Mixer_UI::add_mix_group)); + + session->foreach_mix_group(this, &Mixer_UI::add_mix_group); + + session->StateSaved.connect (slot (*this, &Mixer_UI::session_state_saved)); + redisplay_snapshots (); + + _plugin_selector->set_session (session); + + start_updating (); +} + +void +Mixer_UI::disconnect_from_session () +{ + ENSURE_GUI_THREAD(slot (*this, &Mixer_UI::disconnect_from_session)); + + group_list.clear (); + set_title (_("ardour: mixer")); + stop_updating (); + hide_all_strips (false); +} + +void +Mixer_UI::hide_all_strips (bool with_select) +{ + MixerStrip* ms; + CList_Helpers::RowList::iterator i; + + track_display_list.freeze (); + + for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) { + ms = (MixerStrip *) i->get_data (); + + if (with_select) { + i->unselect (); + } else { + hide_strip (ms); + } + } + + track_display_list.thaw (); +} + +void +Mixer_UI::unselect_all_strips () +{ + hide_all_strips (false); +} + +void +Mixer_UI::select_all_strips () +{ + CList_Helpers::RowList::iterator i; + + for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) { + i->select (); + } +} + +void +Mixer_UI::select_all_audiotrack_strips () +{ + MixerStrip* ms; + CList_Helpers::RowList::iterator i; + + track_display_list.freeze (); + + for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) { + ms = (MixerStrip *) i->get_data (); + + if (ms->is_audio_track()) { + i->select (); + } + } + + track_display_list.thaw (); +} + +void +Mixer_UI::unselect_all_audiotrack_strips () +{ + MixerStrip* ms; + CList_Helpers::RowList::iterator i; + + track_display_list.freeze (); + + for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) { + ms = (MixerStrip *) i->get_data (); + + if (ms->is_audio_track()) { + i->unselect (); + } + } + + track_display_list.thaw (); +} + +void +Mixer_UI::select_all_audiobus_strips () +{ + MixerStrip* ms; + CList_Helpers::RowList::iterator i; + + track_display_list.freeze (); + + for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) { + ms = (MixerStrip *) i->get_data (); + + if (!ms->is_audio_track()) { + i->select (); + } + } + + track_display_list.thaw (); +} + +void +Mixer_UI::unselect_all_audiobus_strips () +{ + MixerStrip* ms; + CList_Helpers::RowList::iterator i; + + track_display_list.freeze (); + + for (i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i) { + ms = (MixerStrip *) i->get_data (); + + if (!ms->is_audio_track()) { + i->unselect (); + } + } + + track_display_list.thaw (); +} + +void +Mixer_UI::show_strip (MixerStrip* ms) +{ + if (!ms->packed()) { + + if (ms->route().master() || ms->route().control()) { + out_packer.pack_start (*ms, false, false); + } else { + strip_packer.pack_start (*ms, false, false); + } + ms->set_packed (true); + ms->show (); + + } +} + +void +Mixer_UI::hide_strip (MixerStrip* ms) +{ + if (ms->packed()) { + if (ms->route().master() || ms->route().control()) { + out_packer.remove (*ms); + } else { + strip_packer.remove (*ms); + } + ms->set_packed (false); + } +} + +gint +Mixer_UI::start_updating () +{ + screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (slot (*this, &Mixer_UI::update_strips)); + fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (slot (*this, &Mixer_UI::fast_update_strips)); + return 0; +} + +gint +Mixer_UI::stop_updating () +{ + screen_update_connection.disconnect(); + fast_screen_update_connection.disconnect(); + return 0; +} + +void +Mixer_UI::update_strips () +{ + if (is_mapped () && session) { + for (list::iterator i = strips.begin(); i != strips.end(); ++i) { + (*i)->update (); + } + } +} + +void +Mixer_UI::fast_update_strips () +{ + if (is_mapped () && session) { + for (list::iterator i = strips.begin(); i != strips.end(); ++i) { + (*i)->fast_update (); + } + } +} + +void +Mixer_UI::snapshot_display_selected (gint row, gint col, GdkEvent* ev) +{ + string* snap_name; + + if ((snap_name = (string*) snapshot_display.get_row_data(row)) != 0){ + if (session->snap_name() == *snap_name){ + return; + } + string path = session->path(); + ARDOUR_UI::instance()->load_session(path, *snap_name); + } +} + +void +Mixer_UI::track_display_selected (gint row, gint col, GdkEvent* ev) +{ + MixerStrip* strip; + + if ((strip = (MixerStrip *) track_display_list.get_row_data (row)) != 0) { + strip->set_marked_for_display (true); + show_strip (strip); + + /* just redraw the whole thing so that we get the right order + when we reinsert the strip. + */ + + track_display_reordered (); + } +} + +void +Mixer_UI::track_display_unselected (gint row, gint col, GdkEvent* ev) +{ + MixerStrip* strip; + + if ((strip = (MixerStrip *) track_display_list.get_row_data (row)) != 0) { + strip->set_marked_for_display (false); + hide_strip (strip); + } +} + +void +Mixer_UI::unselect_strip_in_display (MixerStrip *strip) +{ + CList_Helpers::RowIterator i; + + if ((i = track_display_list.rows().find_data (strip)) != track_display_list.rows().end()) { + (*i).unselect (); + } +} + +void +Mixer_UI::select_strip_in_display (MixerStrip *strip) +{ + CList_Helpers::RowIterator i; + + if ((i = track_display_list.rows().find_data (strip)) != track_display_list.rows().end()) { + (*i).select (); + } +} + +void +Mixer_UI::queue_track_display_reordered (gint arg1, gint arg2) +{ + /* the problem here is that we are called *before* the + list has been reordered. so just queue up + the actual re-drawer to happen once the re-ordering + is complete. + */ + + Main::idle.connect (slot (*this, &Mixer_UI::track_display_reordered)); +} + +int +Mixer_UI::track_display_reordered () +{ + CList_Helpers::RowList::iterator i; + long order; + + // hide_all_strips (false); + + for (order = 0, i = track_display_list.rows().begin(); i != track_display_list.rows().end(); ++i, ++order) { + MixerStrip* strip = (MixerStrip *) (*i)->get_data (); + if (strip->marked_for_display()) { + strip->route().set_order_key (N_("signal"), order); + strip_packer.reorder_child (*strip, -1); /* put at end */ + } + } + + return FALSE; +} + +void +Mixer_UI::track_column_click (gint col) +{ + if (track_menu == 0) { + build_track_menu (); + } + + track_menu->popup (0, 0); +} + +void +Mixer_UI::build_track_menu () +{ + using namespace Menu_Helpers; + using namespace Gtk; + + track_menu = new Menu; + track_menu->set_name ("ArdourContextMenu"); + MenuList& items = track_menu->items(); + track_menu->set_name ("ArdourContextMenu"); + + items.push_back (MenuElem (_("Show All"), slot (*this, &Mixer_UI::select_all_strips))); + items.push_back (MenuElem (_("Hide All"), slot (*this, &Mixer_UI::unselect_all_strips))); + items.push_back (MenuElem (_("Show All AudioTrack MixerStrips"), slot (*this, &Mixer_UI::select_all_audiotrack_strips))); + items.push_back (MenuElem (_("Hide All AudioTrack MixerStrips"), slot (*this, &Mixer_UI::unselect_all_audiotrack_strips))); + items.push_back (MenuElem (_("Show All AudioBus MixerStrips"), slot (*this, &Mixer_UI::select_all_audiobus_strips))); + items.push_back (MenuElem (_("Hide All AudioBus MixerStrips"), slot (*this, &Mixer_UI::unselect_all_audiobus_strips))); + +} + +void +Mixer_UI::strip_name_changed (void* src, MixerStrip* mx) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Mixer_UI::strip_name_changed), src, mx)); + + CList_Helpers::RowList::iterator i; + + if ((i = track_display_list.rows().find_data (mx)) == track_display_list.rows().end()) { + error << _("track display list item for renamed strip not found!") << endmsg; + return; + } + + track_display_list.cell ((*i)->get_row_num(), 0).set_text (mx->route().name()); +} + +void +Mixer_UI::new_mix_group () +{ + ArdourPrompter prompter; + string result; + + prompter.set_prompt (_("Name for new mix group")); + prompter.done.connect (Main::quit.slot()); + + prompter.show_all (); + + Main::run (); + + if (prompter.status != Gtkmmext::Prompter::entered) { + return; + } + + prompter.get_result (result); + + if (result.length()) { + session->add_mix_group (result); + } +} + +void +Mixer_UI::group_list_button_clicked () +{ + if (session) { + new_mix_group (); + } +} + +gint +Mixer_UI::group_list_button_press_event (GdkEventButton* ev) +{ + gint row, col; + RouteGroup* group; + + if (group_list.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) == 0) { + return FALSE; + } + + switch (col) { + case 1: + if (Keyboard::is_edit_event (ev)) { + // RouteGroup* group = (RouteGroup *) group_list.row(row).get_data (); + + // edit_mix_group (group); + + return stop_signal (group_list, "button_press_event"); + + } else { + /* allow regular select to occur */ + return FALSE; + } + + case 0: + stop_signal (group_list, "button_press_event"); + if ((group = (RouteGroup *) group_list.row(row).get_data ()) != 0) { + group->set_active (!group->is_active (), this); + } + break; + } + + return TRUE; +} + +void +Mixer_UI::group_selected (gint row, gint col, GdkEvent* ev) +{ + RouteGroup* group = (RouteGroup *) group_list.row(row).get_data (); + + if (group) { + group->set_hidden (false, this); + } else { + /* the master group */ + + for (list::iterator i = strips.begin(); i != strips.end(); ++i) { + show_strip (*i); + } + + track_display_reordered (); + } +} + +void +Mixer_UI::group_unselected (gint row, gint col, GdkEvent* ev) + +{ + RouteGroup* group = (RouteGroup *) group_list.row(row).get_data (); + + if (group) { + group->set_hidden (true, this); + } else { + /* the master group */ + + for (list::iterator i = strips.begin(); i != strips.end(); ++i) { + hide_strip (*i); + } + } +} + +void +Mixer_UI::group_flags_changed (void* src, RouteGroup* group) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Mixer_UI::group_flags_changed), src, group)); + + if (src != this) { + // select row + } + + CList_Helpers::RowIterator ri = group_list.rows().find_data (group); + + for (list::iterator i = strips.begin(); i != strips.end(); ++i) { + if ((*i)->route().mix_group() == group) { + if (group->is_hidden ()) { + unselect_strip_in_display(*i); + } else { + select_strip_in_display(*i); + (*ri)->select(); + } + } + } + + if (group->is_active()) { + group_list.cell (ri->get_row_num(),0).set_pixmap (check_pixmap, check_mask); + } else { + group_list.cell (ri->get_row_num(),0).set_pixmap (empty_pixmap, empty_mask); + } +} + +void +Mixer_UI::add_mix_group (RouteGroup* group) + +{ + ENSURE_GUI_THREAD(bind (slot (*this, &Mixer_UI::add_mix_group), group)); + + list names; + + names.push_back (""); + names.push_back (group->name()); + + group_list.rows().push_back (names); + group_list.rows().back().set_data (group); + + /* update display to reflect group flags */ + + group_flags_changed (0, group); + + group->FlagsChanged.connect (bind (slot (*this, &Mixer_UI::group_flags_changed), group)); +} + +void +Mixer_UI::redisplay_snapshots () +{ + if (session == 0) { + return; + } + + vector* states; + if ((states = session->possible_states()) == 0) { + return; + } + + snapshot_display.freeze(); + snapshot_display.rows().clear (); + + for (vector::iterator i = states->begin(); i != states->end(); ++i) { + string statename = *(*i); + const char *rowtext[1]; + + rowtext[0] = statename.c_str(); + + snapshot_display.rows().push_back (rowtext); + snapshot_display.rows().back().set_data (new string (statename), deferred_delete); + + delete *i; + } + + delete states; + snapshot_display.thaw(); +} + +void +Mixer_UI::session_state_saved (string snap_name) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &Mixer_UI::session_state_saved), snap_name)); + redisplay_snapshots (); +} + +gint +Mixer_UI::strip_scroller_button_release (GdkEventButton* ev) +{ + using namespace Menu_Helpers; + + if (Keyboard::is_context_menu_event (ev)) { + ARDOUR_UI::instance()->add_route(); + return TRUE; + } + + return FALSE; +} + +void +Mixer_UI::set_strip_width (Width w) +{ + _strip_width = w; + + for (list::iterator i = strips.begin(); i != strips.end(); ++i) { + (*i)->set_width (w); + } +} + + +int +Mixer_UI::set_state (const XMLNode& node) +{ + const XMLProperty* prop; + XMLNode* geometry; + int x, y, width, height, xoff, yoff; + + if ((geometry = find_named_node (node, "geometry")) == 0) { + + width = default_width; + height = default_height; + x = 1; + y = 1; + xoff = 0; + yoff = 21; + + } else { + + width = atoi(geometry->property("x_size")->value().c_str()); + height = atoi(geometry->property("y_size")->value().c_str()); + x = atoi(geometry->property("x_pos")->value().c_str()); + y = atoi(geometry->property("y_pos")->value().c_str()); + xoff = atoi(geometry->property("x_off")->value().c_str()); + yoff = atoi(geometry->property("y_off")->value().c_str()); + } + + set_default_size(width, height); + set_uposition(x, y-yoff); + + if ((prop = node.property ("narrow-strips"))) { + if (prop->value() == "yes") { + set_strip_width (Narrow); + } else { + set_strip_width (Wide); + } + } + + return 0; +} + +XMLNode& +Mixer_UI::get_state (void) +{ + XMLNode* node = new XMLNode ("Mixer"); + + if (is_realized()) { + Gdk_Window win = get_window(); + + int x, y, xoff, yoff, width, height; + win.get_root_origin(x, y); + win.get_position(xoff, yoff); + win.get_size(width, height); + + XMLNode* geometry = new XMLNode ("geometry"); + char buf[32]; + snprintf(buf, sizeof(buf), "%d", width); + geometry->add_property(X_("x_size"), string(buf)); + snprintf(buf, sizeof(buf), "%d", height); + geometry->add_property(X_("y_size"), string(buf)); + snprintf(buf, sizeof(buf), "%d", x); + geometry->add_property(X_("x_pos"), string(buf)); + snprintf(buf, sizeof(buf), "%d", y); + geometry->add_property(X_("y_pos"), string(buf)); + snprintf(buf, sizeof(buf), "%d", xoff); + geometry->add_property(X_("x_off"), string(buf)); + snprintf(buf, sizeof(buf), "%d", yoff); + geometry->add_property(X_("y_off"), string(buf)); + + snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast(&rhs_pane1)->gtkobj())); + geometry->add_property(X_("mixer_rhs_pane1_pos"), string(buf)); + snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast(&rhs_pane2)->gtkobj())); + geometry->add_property(X_("mixer_rhs_pane2_pos"), string(buf)); + snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast(&list_hpane)->gtkobj())); + geometry->add_property(X_("mixer_list_hpane_pos"), string(buf)); + + node->add_child_nocopy (*geometry); + } + + node->add_property ("narrow-strips", _strip_width == Narrow ? "yes" : "no"); + + return *node; +} + + +void +Mixer_UI::pane_allocation_handler (GtkAllocation *alloc, Gtk::Paned* which) +{ + int pos; + XMLProperty* prop = 0; + char buf[32]; + XMLNode* node = ARDOUR_UI::instance()->mixer_settings(); + XMLNode* geometry; + int width, height; + static int32_t done[3] = { 0, 0, 0 }; + + if ((geometry = find_named_node (*node, "geometry")) == 0) { + width = default_width; + height = default_height; + } else { + width = atoi(geometry->property("x_size")->value()); + height = atoi(geometry->property("y_size")->value()); + } + + if (which == static_cast (&rhs_pane1)) { + + if (done[0]) { + return; + } + + if (!geometry || (prop = geometry->property("mixer_rhs_pane1_pos")) == 0) { + pos = height / 3; + snprintf (buf, sizeof(buf), "%d", pos); + } else { + pos = atoi (prop->value()); + } + + if ((done[0] = GTK_WIDGET(rhs_pane1.gtkobj())->allocation.height > pos)) { + rhs_pane1.set_position (pos); + } + + } else if (which == static_cast (&rhs_pane2)) { + + if (done[1]) { + return; + } + + if (!geometry || (prop = geometry->property("mixer_rhs_pane2_pos")) == 0) { + pos = height / 3; + snprintf (buf, sizeof(buf), "%d", pos); + } else { + pos = atoi (prop->value()); + } + + if ((done[1] = GTK_WIDGET(rhs_pane2.gtkobj())->allocation.height > pos)) { + rhs_pane2.set_position (pos); + } + + } else if (which == static_cast (&list_hpane)) { + + if (done[2]) { + return; + } + + if (!geometry || (prop = geometry->property("mixer_list_hpane_pos")) == 0) { + pos = 75; + snprintf (buf, sizeof(buf), "%d", pos); + } else { + pos = atoi (prop->value()); + } + + if ((done[2] = GTK_WIDGET(list_hpane.gtkobj())->allocation.width > pos)) { + list_hpane.set_position (pos); + } + } +} + diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h new file mode 100644 index 0000000000..2027f905f3 --- /dev/null +++ b/gtk2_ardour/mixer_ui.h @@ -0,0 +1,180 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_mixer_ui_h__ +#define __ardour_mixer_ui_h__ + +#include + +#include + +#include +#include +#include + +#include "keyboard_target.h" +#include "route_redirect_selection.h" +#include "enums.h" + +namespace ARDOUR { + class Route; + class RouteGroup; + class Session; + class DiskStream; + class AudioEngine; +}; + +class MixerStrip; +class PluginSelector; + +class Mixer_UI : public Gtk::Window, public KeyboardTarget +{ + public: + Mixer_UI (ARDOUR::AudioEngine&); + ~Mixer_UI(); + + void connect_to_session (ARDOUR::Session *); + + PluginSelector& plugin_selector() { return *_plugin_selector; } + + void set_strip_width (Width); + Width get_strip_width () const { return _strip_width; } + + void unselect_strip_in_display (MixerStrip*); + void select_strip_in_display (MixerStrip*); + + XMLNode& get_state (void); + int set_state (const XMLNode& ); + + void show_window (); + + void ensure_float (Gtk::Window&); + + RouteRedirectSelection& selection() { return _selection; } + + private: + ARDOUR::AudioEngine& engine; + ARDOUR::Session *session; + + Gtk::HBox global_hpacker; + Gtk::VBox global_vpacker; + Gtk::ScrolledWindow scroller; + Gtk::EventBox scroller_base; + Gtk::HBox scroller_hpacker; + Gtk::VBox mixer_scroller_vpacker; + Gtk::VBox list_vpacker; + Gtk::CList track_display_list; + Gtk::CList group_list; + Gtk::Label group_list_button_label; + Gtk::Button group_list_button; + Gtk::ScrolledWindow track_display_scroller; + Gtk::ScrolledWindow group_list_scroller; + Gtk::VBox group_list_vbox; + Gtk::Frame track_display_frame; + Gtk::Frame group_list_frame; + Gtk::VPaned rhs_pane1; + Gtk::VPaned rhs_pane2; + Gtk::HBox strip_packer; + Gtk::HBox out_packer; + Gtk::HPaned list_hpane; + + void pane_allocation_handler (GtkAllocation*, Gtk::Paned*); + + list strips; + + gint strip_scroller_button_release (GdkEventButton*); + + void add_strip (ARDOUR::Route*); + void remove_strip (MixerStrip *); + + void show_strip (MixerStrip *); + void hide_strip (MixerStrip *); + + void hide_all_strips (bool with_select); + void unselect_all_strips(); + void select_all_strips (); + void unselect_all_audiotrack_strips (); + void select_all_audiotrack_strips (); + void unselect_all_audiobus_strips (); + void select_all_audiobus_strips (); + + void follow_strip_selection (); + + gint start_updating (); + gint stop_updating (); + + void disconnect_from_session (); + + SigC::Connection screen_update_connection; + void update_strips (); + SigC::Connection fast_screen_update_connection; + void fast_update_strips (); + + void snapshot_display_selected (gint row, gint col, GdkEvent* ev); + + void track_display_selected (gint row, gint col, GdkEvent *ev); + void track_display_unselected (gint row, gint col, GdkEvent *ev); + void queue_track_display_reordered (gint row, gint col); + gint track_display_reordered (); + void track_name_changed (MixerStrip *); + + void group_selected (gint row, gint col, GdkEvent *ev); + void group_unselected (gint row, gint col, GdkEvent *ev); + gint group_list_button_press_event (GdkEventButton *); + void group_list_button_clicked(); + void new_mix_group (); + void add_mix_group (ARDOUR::RouteGroup *); + + Gtk::Menu *track_menu; + void track_column_click (gint); + void build_track_menu (); + + PluginSelector *_plugin_selector; + + void strip_name_changed (void *src, MixerStrip *); + + static GdkPixmap *check_pixmap; + static GdkBitmap *check_mask; + static GdkPixmap *empty_pixmap; + static GdkBitmap *empty_mask; + + void group_flags_changed (void *src, ARDOUR::RouteGroup *); + + /* snapshots */ + + Gtk::CList snapshot_display; + Gtk::ScrolledWindow snapshot_display_scroller; + + void redisplay_snapshots(); + void session_state_saved (string); + + gint strip_button_release_event (GdkEventButton*, MixerStrip*); + + RouteRedirectSelection _selection; + + Width _strip_width; + + static const int32_t default_width = -1; + static const int32_t default_height = 765; +}; + +#endif /* __ardour_mixer_ui_h__ */ + + diff --git a/gtk2_ardour/new_session_dialog.cc b/gtk2_ardour/new_session_dialog.cc new file mode 100644 index 0000000000..2d3888c731 --- /dev/null +++ b/gtk2_ardour/new_session_dialog.cc @@ -0,0 +1,342 @@ +/* + Copyright (C) 1999-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include + +#include "prompter.h" +#include "new_session_dialog.h" + +using namespace Gtkmmext; +using namespace Gtk; +using namespace ARDOUR; + +#include "i18n.h" + +extern std::vector channel_combo_strings; + +NewSessionDialog::NewSessionDialog (ARDOUR::AudioEngine& engine, bool startup, string given_path) + : ArdourDialog ("new session dialog"), + file_selector (_("Session name:"), _("Create")), + use_control_button (_("use control outs")), + use_master_button (_("use master outs")), + connect_to_physical_inputs_button (_("automatically connect track inputs to physical ports")), + connect_to_master_button (_("automatically connect track outputs to master outs")), + connect_to_physical_outputs_button (_("automatically connect track outputs to physical ports")), + manual_connect_outputs_button (_("manually connect track outputs")), + in_count_adjustment (2, 1, 1000, 1, 2), + out_count_adjustment (2, 1, 1000, 1, 2), + output_label (_("Output Connections")), + input_label (_("Input Connections")), + expansion_button (_("Advanced...")), + out_table (2, 2), + show_again (_("show again")), + in_count_spinner (in_count_adjustment), + out_count_spinner (out_count_adjustment), + in_count_label (_("Hardware Inputs: use")), + out_count_label (_("Hardware Outputs: use")) + +{ + using namespace Notebook_Helpers; + + set_name ("NewSessionDialog"); + set_title (_("new session setup")); + set_wmclass (_("ardour_new_session"), "Ardour"); + set_position (GTK_WIN_POS_MOUSE); + set_keyboard_input (true); + set_policy (false, true, false); + set_modal (true); + + /* sample rate */ + + sr_label1.set_text (compose + (_("This session will playback and record at %1 Hz"), + engine.frame_rate())); + sr_label2.set_text (_("This rate is set by JACK and cannot be changed.\n" + "If you want to use a different sample rate\n" + "please exit and restart JACK")); + sr_box.set_spacing (12); + sr_box.set_border_width (12); + sr_box.pack_start (sr_label1, false, false); + sr_box.pack_start (sr_label2, false, false); + sr_frame.add (sr_box); + + /* input */ + + connect_to_physical_inputs_button.set_active (true); + connect_to_physical_inputs_button.set_name ("NewSessionDialogButton"); + + HBox* input_limit_box = manage (new HBox); + input_limit_box->set_spacing (7); + input_limit_box->pack_start (in_count_label, false, false); + input_limit_box->pack_start (in_count_spinner, false, false); + + input_label.set_alignment (0.1, 0.5); + input_vbox.pack_start (input_label, false, false, 7); + input_vbox.pack_start (connect_to_physical_inputs_button, false, false); + + if (engine.n_physical_inputs() > 2) { + input_vbox.pack_start (*input_limit_box, false, false); + } + + /* output */ + + use_master_button.set_active (true); + use_master_button.set_name ("NewSessionDialogButton"); + + connect_to_physical_outputs_button.set_group (connect_to_master_button.group()); + manual_connect_outputs_button.set_group (connect_to_master_button.group()); + connect_to_master_button.set_active (true); + + connect_to_physical_outputs_button.set_name ("NewSessionDialogButton"); + manual_connect_outputs_button.set_name ("NewSessionDialogButton"); + connect_to_master_button.set_name ("NewSessionDialogButton"); + use_control_button.set_name ("NewSessionDialogButton"); + + out_count_adjustment.set_value (engine.n_physical_outputs()); + in_count_adjustment.set_value (engine.n_physical_inputs()); + + control_out_channel_combo.set_popdown_strings (channel_combo_strings); + control_out_channel_combo.set_name (X_("NewSessionChannelCombo")); + control_out_channel_combo.get_entry()->set_name (X_("NewSessionChannelCombo")); + control_out_channel_combo.get_popwin()->set_name (X_("NewSessionChannelCombo")); + // use stereo as default + control_out_channel_combo.get_list()->select_item (1); + + master_out_channel_combo.set_popdown_strings (channel_combo_strings); + master_out_channel_combo.set_name (X_("NewSessionChannelCombo")); + master_out_channel_combo.get_entry()->set_name (X_("NewSessionChannelCombo")); + master_out_channel_combo.get_popwin()->set_name (X_("NewSessionChannelCombo")); + // use stereo as default + master_out_channel_combo.get_list()->select_item (1); + + + out_table.set_col_spacings (7); + out_table.set_row_spacings (7); + if (engine.n_physical_outputs() > 2) { + out_table.attach (out_count_label, 0, 1, 0, 1, 0, 0); + out_table.attach (out_count_spinner, 1, 2, 0, 1, 0, 0); + } + out_table.attach (use_control_button, 0, 1, 1, 2, 0, 0); + out_table.attach (control_out_channel_combo, 1, 2, 1, 2, 0, 0); + out_table.attach (use_master_button, 0, 1, 2, 3, 0, 0); + out_table.attach (master_out_channel_combo, 1, 2, 2, 3, 0, 0); + + output_label.set_alignment (0.1, 0.5); + output_vbox.pack_start (output_label, true, true, 7); + output_vbox.pack_start (out_table, false, false, 5); + output_vbox.pack_start (connect_to_master_button, false); + output_vbox.pack_start (connect_to_physical_outputs_button, false); + output_vbox.pack_start (manual_connect_outputs_button, false); + + input_hbox.pack_start (input_vbox, false, false); + output_hbox.pack_start (output_vbox, false, false); + + VBox* template_vbox = manage (new VBox); + Label* template_label = manage (new Label (_("Session template"))); + + template_label->set_alignment (0.1, 0.5); + template_vbox->pack_start (*template_label, true, true, 7); + template_vbox->pack_start (template_combo, false, false); + + io_box.set_border_width (12); + io_box.set_spacing (7); + io_box.pack_start (*template_vbox); + + io_box.pack_start (input_hbox); + io_box.pack_start (output_hbox); + + reset_templates(); + + option_hbox.set_spacing (7); + option_hbox.pack_start (io_box); + + fsbox.set_border_width (12); + fsbox.set_spacing (7); + fsbox.pack_start (file_selector.table, false, false); + + notebook.pages().push_back (TabElem (fsbox, _("Location"))); + notebook.pages().push_back (TabElem (option_hbox, _("Configuration"))); + + if (startup) { + show_again.set_active(true); + show_again.toggled.connect (slot (*this, &NewSessionDialog::show_again_toggled)); + file_selector.button_box.pack_end(show_again, false, false); + } + + main_vbox.set_border_width (12); + main_vbox.set_border_width (12); + main_vbox.set_spacing (7); + main_vbox.pack_start (sr_frame, false, false); + main_vbox.pack_start (notebook, false, false); + main_vbox.pack_start (file_selector.button_box, false, false); + + add (main_vbox); + +// template_selector.shift_made.connect ( +// slot (*this, &NewSessionDialog::mix_template_shift)); +// template_selector.control_made.connect ( +// slot (*this, &NewSessionDialog::mix_template_control)); + + file_selector.cancel_button.clicked.connect (bind (slot (*this, &ArdourDialog::stop), -1)); + file_selector.op_button.clicked.connect (bind (slot (*this, &ArdourDialog::stop), 0)); + file_selector.Expanded.connect (slot (*this, &NewSessionDialog::file_selector_expansion)); + + delete_event.connect (slot (*this, &ArdourDialog::wm_close_event)); + show.connect (slot (*this, &NewSessionDialog::fixup_at_show)); + + file_selector.entry_label.set_name ("NewSessionMainLabel"); + file_selector.where_label.set_name ("NewSessionMainLabel"); + template_label->set_name ("NewSessionIOLabel"); + input_label.set_name ("NewSessionIOLabel"); + output_label.set_name ("NewSessionIOLabel"); + sr_label1.set_name ("NewSessionSR1Label"); + sr_label2.set_name ("NewSessionSR2Label"); + + if (given_path.empty()) { + Session::FavoriteDirs favs; + Session::read_favorite_dirs (favs); + file_selector.set_favorites (favs); + } else { + file_selector.set_path (given_path, true); + notebook.set_page (-1); + notebook.show.connect (bind (slot (notebook, &Notebook::set_page), -1)); + } + + set_default_size(531, 358); +} + +void +NewSessionDialog::file_selector_expansion (bool expanded) +{ + if (expanded) { + fsbox.pack_start (file_selector.expansion_vbox); + fsbox.reorder_child (file_selector.expansion_vbox, 2); + } else { + fsbox.remove (file_selector.expansion_vbox); + } +} + +void +NewSessionDialog::fixup_at_show () +{ +// if (template_selector.clist().rows().size() == 0) { +// use_template_button.set_sensitive (false); +// } + + Session::FavoriteDirs favs; + Session::read_favorite_dirs (favs); + file_selector.set_favorites (favs); + + file_selector.entry.grab_focus (); +} + +void +NewSessionDialog::_mix_template_refiller (CList &clist, void *arg) + +{ + ((NewSessionDialog*) arg)->mix_template_refiller (clist); +} + +void +NewSessionDialog::mix_template_refiller (CList &clist) +{ + const gchar *rowdata[2]; + list templates; + list::iterator i; + + Session::get_template_list(templates); + + rowdata[0] = _("blank"); + clist.insert_row (0, rowdata); + + guint row; + for (row=1, i=templates.begin(); i != templates.end(); ++row, ++i) { + rowdata[0] = (*i).c_str(); + clist.insert_row (row, rowdata); + } +} + +void +NewSessionDialog::mix_template_shift (Gtkmmext::Selector* selector, Gtkmmext::SelectionResult* res) +{ + if (res && res->text){ + Session::delete_template(*res->text); + // template_selector.rescan(); + } +} + +void +NewSessionDialog::mix_template_control (Gtkmmext::Selector* selector, Gtkmmext::SelectionResult* res) +{ +#if 0 + if (res && res->text) { + ArdourPrompter prompter (true); + prompter.set_prompt(_("Name for mix template:")); + + string old_name = *(res->text); + prompter.set_initial_text (old_name); + prompter.done.connect (Gtk::Main::quit.slot()); + prompter.show_all(); + + Gtk::Main::run(); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string name; + + prompter.get_result (name); + + if (name.length() && name != old_name) { + Session::rename_template(old_name, name); + template_selector.rescan(); + } + } + } +#endif +} + +void +NewSessionDialog::show_again_toggled () +{ + Config->set_no_new_session_dialog(!show_again.get_active()); + Config->save_state(); +} + +void +NewSessionDialog::reset_templates () +{ + templates.clear (); + templates.push_back (_("No template - create tracks/busses manually")); + Session::get_template_list (templates); + template_combo.set_popdown_strings (templates); +} + +string +NewSessionDialog::get_template_name() +{ + string str = template_combo.get_entry()->get_text(); + if (str.substr (0, 11) == _("No template")) { + return ""; + } else { + return str; + } +} diff --git a/gtk2_ardour/new_session_dialog.h b/gtk2_ardour/new_session_dialog.h new file mode 100644 index 0000000000..c253861ef6 --- /dev/null +++ b/gtk2_ardour/new_session_dialog.h @@ -0,0 +1,98 @@ +#ifndef __gtk_ardour_new_session_dialog_h__ +#define __gtk_ardour_new_session_dialog_h__ + +#include +#include +#include +#include +#include + +namespace Gtk { + class CList; +} + +namespace ARDOUR { + class AudioEngine; +} + +#include +#include +#include +#include "ardour_dialog.h" + +class NewSessionDialog : public ArdourDialog +{ + public: + NewSessionDialog (ARDOUR::AudioEngine&, bool startup, std::string path); + + Gtkmmext::NewSaveDialog file_selector; + Gtk::Combo control_out_channel_combo; + Gtk::Combo master_out_channel_combo; + Gtk::CheckButton use_control_button; + Gtk::CheckButton use_master_button; + Gtk::CheckButton connect_to_physical_inputs_button; + + Gtk::RadioButton connect_to_master_button; + Gtk::RadioButton connect_to_physical_outputs_button; + Gtk::RadioButton manual_connect_outputs_button; + + Gtk::VBox input_vbox; + Gtk::VBox manual_vbox; + Gtk::VBox output_vbox; + Gtk::VBox vbox; + + Gtk::Adjustment in_count_adjustment; + Gtk::Adjustment out_count_adjustment; + + string get_template_name (); + + private: + Gtk::Notebook notebook; + Gtk::VBox main_vbox; + Gtk::VBox fsbox; + + Gtk::Frame control_out_config_frame; + Gtk::Frame master_out_config_frame; + Gtk::Label output_label; + Gtk::Label input_label; + Gtk::Frame sr_frame; + Gtk::Frame template_frame; + Gtk::Frame manual_frame; + Gtk::HBox control_hbox; + Gtk::HBox master_hbox; + Gtk::Table io_table; + Gtk::VBox template_box; + Gtk::HBox output_hbox; + Gtk::HBox input_hbox; + Gtk::HBox option_hbox; + Gtk::VBox io_box; + Gtk::Label sr_label2; + Gtk::Label sr_label1; + Gtk::VBox sr_box; + Gtk::Button expansion_button; + Gtk::Table out_table; + Gtk::CheckButton show_again; + Gtk::Combo template_combo; + list templates; + Gtk::SpinButton in_count_spinner; + Gtk::SpinButton out_count_spinner; + Gtk::Label in_count_label; + Gtk::Label out_count_label; + + void reset_templates (); + + static void _mix_template_refiller (Gtk::CList &clist, void *); + void mix_template_refiller (Gtk::CList &clist); + + void mix_template_shift (Gtkmmext::Selector *, Gtkmmext::SelectionResult*); + void mix_template_control (Gtkmmext::Selector *, Gtkmmext::SelectionResult*); + + void fixup_at_realize (); + void fixup_at_show (); + void toggle_expansion (); + void file_selector_expansion (bool); + + void show_again_toggled (); +}; + +#endif // __gtk_ardour_new_session_dialog_h__ */ diff --git a/gtk2_ardour/option_editor.cc b/gtk2_ardour/option_editor.cc new file mode 100644 index 0000000000..fba414ebc8 --- /dev/null +++ b/gtk2_ardour/option_editor.cc @@ -0,0 +1,2051 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "public_editor.h" +#include "mixer_ui.h" +#include "ardour_ui.h" +#include "io_selector.h" +#include "gain_meter.h" +#include "library_ui.h" +#include "utils.h" +#include "editing.h" +#include "option_editor.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; +using namespace Editing; +using namespace Gtkmmext; + +static const gchar *psync_strings[] = { + N_("Internal"), + N_("Slave to MTC"), + N_("Sync with JACK"), + N_("never used but stops crashes"), + 0 +}; + +static const gchar *lmode_strings[] = { + N_("Later regions are higher"), + N_("Most recently added/moved/trimmed regions are higher"), + N_("Most recently added regions are higher"), + 0 +}; + +static const gchar *xfl_strings[] = { + N_("Span entire region overlap"), + N_("Short fades at the start of the overlap"), + 0 +}; + +static vector positional_sync_strings; +static vector layer_mode_strings; +static vector xfade_model_strings; + +OptionEditor::OptionEditor (ARDOUR_UI& uip, PublicEditor& ed, Mixer_UI& mixui) + : ArdourDialog ("option editor"), + ui (uip), + editor (ed), + mixer (mixui), + + path_table (9, 2), + + /* Fades */ + + auto_xfade_button (_("Automatically create crossfades")), + xfade_active_button (_("New full-overlap crossfades are unmuted")), + layer_mode_label (_("Region layering mode")), + xfade_model_label (_("Crossfade model")), + short_xfade_adjustment (0, 1.0, 500.0, 5.0, 100.0), + short_xfade_slider (short_xfade_adjustment), + + /* solo */ + solo_latched_button (_("Latched solo")), + solo_via_bus_button (_("Solo via bus")), + + /* display */ + + show_waveforms_button (_("Show waveforms")), + show_waveforms_recording_button (_("Show waveforms while recording")), + mixer_strip_width_button (_("Narrow mixer strips")), + show_measures_button (_("Show measure lines")), + follow_playhead_button (_("Follow playhead")), + + /* Sync */ + + send_mtc_button (_("Send MTC")), + send_mmc_button (_("Send MMC")), + jack_time_master_button (_("JACK time master")), + smpte_offset_clock (X_("SMPTEOffsetClock"), true, true), + smpte_offset_negative_button (_("SMPTE offset is negative")), + + /* MIDI */ + + midi_feedback_button (_("Send MIDI parameter feedback")), + midi_control_button (_("MIDI parameter control")), + mmc_control_button (_("MMC control")), + + /* Click */ + + click_table (2, 3), + click_browse_button (_("Browse")), + click_emphasis_browse_button (_("Browse")), + + /* kbd/mouse */ + + keyboard_mouse_table (3, 4), + delete_button_adjustment (3, 1, 5), + delete_button_spin (delete_button_adjustment), + edit_button_adjustment (3, 1, 5), + edit_button_spin (edit_button_adjustment), + + /* Misc */ + + auto_connect_inputs_button (_("Auto-connect new track inputs to hardware")), + auto_connect_output_physical_button (_("Auto-connect new track outputs to hardware")), + auto_connect_output_master_button (_("Auto-connect new track outputs to master bus")), + auto_connect_output_manual_button (_("Manually connect new track outputs")), + hw_monitor_button(_("Use Hardware Monitoring")), + sw_monitor_button(_("Use Software Monitoring")), + plugins_stop_button (_("Stop plugins with transport")), + plugins_on_rec_button (_("Run plugins while recording")), + verify_remove_last_capture_button (_("Verify remove last capture")), + stop_rec_on_xrun_button (_("Stop recording on xrun")), + stop_at_end_button (_("Stop transport at end of session")), + debug_keyboard_button (_("Debug keyboard events")), + speed_quieten_button (_("-12dB gain reduction for ffwd/rew")) + +{ + using namespace Notebook_Helpers; + + click_io_selector = 0; + auditioner_io_selector = 0; + + set_default_size (300, 300); + set_title (_("ardour: options editor")); + set_wmclass (_("ardour_option_editor"), "Ardour"); + + set_name ("OptionsWindow"); + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK); + + layer_mode_label.set_name ("OptionsLabel"); + xfade_model_label.set_name ("OptionsLabel"); + + VBox *vbox = manage(new VBox); + add (*vbox); + set_border_width (3); + + vbox->set_spacing (4); + vbox->pack_start(notebook); + + delete_event.connect (slot (*this, &OptionEditor::wm_close)); + + notebook.set_show_tabs (true); + notebook.set_show_border (true); + notebook.set_name ("OptionsNotebook"); + + setup_sync_options(); + setup_path_options(); + setup_fade_options (); + setup_solo_options (); + setup_display_options (); + setup_misc_options (); + setup_keyboard_options (); + setup_auditioner_editor (); + + notebook.pages().push_back (TabElem (misc_packer, _("Misc"))); + notebook.pages().push_back (TabElem (sync_packer, _("Sync"))); + notebook.pages().push_back (TabElem (path_table, _("Paths/Files"))); + notebook.pages().push_back (TabElem (display_packer, _("Display"))); + notebook.pages().push_back (TabElem (keyboard_mouse_table, _("Kbd/Mouse"))); + notebook.pages().push_back (TabElem (click_packer, _("Click"))); + notebook.pages().push_back (TabElem (audition_packer, _("Audition"))); + notebook.pages().push_back (TabElem (fade_packer, _("Layers & Fades"))); + notebook.pages().push_back (TabElem (solo_packer, _("Solo"))); + + if (!MIDI::Manager::instance()->get_midi_ports().empty()) { + setup_midi_options (); + notebook.pages().push_back (TabElem (midi_packer, _("MIDI"))); + } + + set_session (0); +} + +void +OptionEditor::set_session (Session *s) +{ + clear_click_editor (); + clear_auditioner_editor (); + + click_path_entry.set_text (""); + click_emphasis_path_entry.set_text (""); + session_raid_entry.set_text (""); + + send_mtc_button.set_sensitive (false); + send_mmc_button.set_sensitive (false); + midi_feedback_button.set_sensitive (false); + midi_control_button.set_sensitive (false); + mmc_control_button.set_sensitive (false); + click_path_entry.set_sensitive (false); + click_emphasis_path_entry.set_sensitive (false); + session_raid_entry.set_sensitive (false); + plugins_on_rec_button.set_sensitive (false); + verify_remove_last_capture_button.set_sensitive (false); + slave_type_combo.set_sensitive (false); + solo_latched_button.set_sensitive (false); + solo_via_bus_button.set_sensitive (false); + smpte_fps_combo.set_sensitive (false); + meter_hold_combo.set_sensitive (false); + meter_falloff_combo.set_sensitive (false); + auto_connect_inputs_button.set_sensitive (false); + auto_connect_output_physical_button.set_sensitive (false); + auto_connect_output_master_button.set_sensitive (false); + auto_connect_output_manual_button.set_sensitive (false); + layer_mode_combo.set_sensitive (false); + short_xfade_slider.set_sensitive (false); + smpte_offset_negative_button.set_sensitive (false); + + smpte_offset_clock.set_session (s); + + if ((session = s) == 0) { + return; + } + + send_mtc_button.set_sensitive (true); + send_mmc_button.set_sensitive (true); + midi_feedback_button.set_sensitive (true); + midi_control_button.set_sensitive (true); + mmc_control_button.set_sensitive (true); + click_path_entry.set_sensitive (true); + click_emphasis_path_entry.set_sensitive (true); + session_raid_entry.set_sensitive (true); + plugins_on_rec_button.set_sensitive (true); + verify_remove_last_capture_button.set_sensitive (true); + slave_type_combo.set_sensitive (true); + solo_latched_button.set_sensitive (true); + solo_via_bus_button.set_sensitive (true); + smpte_fps_combo.set_sensitive (true); + meter_hold_combo.set_sensitive (true); + meter_falloff_combo.set_sensitive (true); + auto_connect_inputs_button.set_sensitive (true); + auto_connect_output_physical_button.set_sensitive (true); + auto_connect_output_master_button.set_sensitive (true); + auto_connect_output_manual_button.set_sensitive (true); + layer_mode_combo.set_sensitive (true); + short_xfade_slider.set_sensitive (true); + smpte_offset_negative_button.set_sensitive (true); + + if (!s->smpte_drop_frames) { + // non-drop frames + if (s->smpte_frames_per_second == 24.0) + smpte_fps_combo.get_entry ()->set_text (_("24 FPS")); + else if (s->smpte_frames_per_second == 25.0) + smpte_fps_combo.get_entry ()->set_text (_("25 FPS")); + else if (s->smpte_frames_per_second == 30.0) + smpte_fps_combo.get_entry ()->set_text (_("30 FPS")); + else + smpte_fps_combo.get_entry ()->set_text (_("???")); + } else { + // drop frames + if (floor(s->smpte_frames_per_second) == 29.0) + smpte_fps_combo.get_entry ()->set_text (_("30 FPS drop")); + else + smpte_fps_combo.get_entry ()->set_text (_("???")); + } + + smpte_offset_clock.set_session (s); + smpte_offset_clock.set (s->smpte_offset (), true); + + smpte_offset_negative_button.set_active (session->smpte_offset_negative()); + send_mtc_button.set_active (session->get_send_mtc()); + + /* MIDI I/O */ + + send_mmc_button.set_active (session->get_send_mmc()); + midi_control_button.set_active (session->get_midi_control()); + midi_feedback_button.set_active (session->get_midi_feedback()); + mmc_control_button.set_active (session->get_mmc_control()); + + /* set up port assignments */ + + map >::iterator res; + + if (session->mtc_port()) { + if ((res = port_toggle_buttons.find (session->mtc_port())) != port_toggle_buttons.end()) { + (*res).second[MtcIndex]->set_active (true); + } + } + + if (session->mmc_port ()) { + if ((res = port_toggle_buttons.find (session->mmc_port())) != port_toggle_buttons.end()) { + (*res).second[MmcIndex]->set_active (true); + } + } + + if (session->midi_port()) { + if ((res = port_toggle_buttons.find (session->midi_port())) != port_toggle_buttons.end()) { + (*res).second[MidiIndex]->set_active (true); + } + } + + auto_connect_inputs_button.set_active (session->get_input_auto_connect()); + + Session::AutoConnectOption oac = session->get_output_auto_connect(); + if (oac & Session::AutoConnectPhysical) { + auto_connect_output_physical_button.set_active (true); + } else if (oac & Session::AutoConnectMaster) { + auto_connect_output_master_button.set_active (true); + } else { + auto_connect_output_manual_button.set_active (true); + } + + setup_click_editor (); + connect_audition_editor (); + + plugins_on_rec_button.set_active (session->get_recording_plugins ()); + verify_remove_last_capture_button.set_active (Config->get_verify_remove_last_capture()); + + layer_mode_combo.get_entry()->set_text (layer_mode_strings[session->get_layer_model()]); + xfade_model_combo.get_entry()->set_text (xfade_model_strings[session->get_xfade_model()]); + + short_xfade_adjustment.set_value ((Crossfade::short_xfade_length() / (float) session->frame_rate()) * 1000.0); + + xfade_active_button.set_active (session->get_crossfades_active()); + solo_latched_button.set_active (session->solo_latched()); + solo_via_bus_button.set_active (session->solo_model() == Session::SoloBus); + + add_session_paths (); + + vector dumb; + dumb.push_back (positional_sync_strings[Session::None]); + dumb.push_back (positional_sync_strings[Session::JACK]); + if (session->mtc_port()) { + dumb.push_back (positional_sync_strings[Session::MTC]); + } + slave_type_combo.set_popdown_strings (dumb); + + // meter stuff + if (session->meter_falloff() == 0.0f) { + meter_falloff_combo.get_entry ()->set_text (_("Off")); + } else if (session->meter_falloff() <= 0.3f) { + meter_falloff_combo.get_entry ()->set_text (_("Slowest")); + } else if (session->meter_falloff() <= 0.4f) { + meter_falloff_combo.get_entry ()->set_text (_("Slow")); + } else if (session->meter_falloff() <= 0.8f) { + meter_falloff_combo.get_entry ()->set_text (_("Medium")); + } else if (session->meter_falloff() <= 1.4f) { + meter_falloff_combo.get_entry ()->set_text (_("Fast")); + } else if (session->meter_falloff() <= 2.0f) { + meter_falloff_combo.get_entry ()->set_text (_("Faster")); + } else { + meter_falloff_combo.get_entry ()->set_text (_("Fastest")); + } + + switch ((int) floor (session->meter_hold())) { + case 0: + meter_hold_combo.get_entry ()->set_text (_("Off")); + break; + case 40: + meter_hold_combo.get_entry ()->set_text (_("Short")); + break; + case 100: + meter_hold_combo.get_entry ()->set_text (_("Medium")); + break; + case 200: + meter_hold_combo.get_entry ()->set_text (_("Long")); + break; + } + + session_control_changed (Session::SlaveType); + session_control_changed (Session::AlignChoice); + session->ControlChanged.connect (slot (*this, &OptionEditor::queue_session_control_changed)); +} + +OptionEditor::~OptionEditor () +{ +} + +static const gchar *native_format_strings[] = { + N_("Broadcast WAVE/floating point"), + N_("WAVE/floating point"), + 0 +}; + +void +OptionEditor::setup_path_options() +{ + Gtk::Label* label; + + path_table.set_homogeneous (true); + path_table.set_border_width (12); + path_table.set_row_spacings (5); + + session_raid_entry.set_name ("OptionsEntry"); + + session_raid_entry.activate.connect (slot (*this, &OptionEditor::raid_path_changed)); + + session_raid_entry.focus_in_event.connect (slot (Keyboard::the_keyboard(), &Keyboard::focus_in_handler)); + session_raid_entry.focus_out_event.connect (bind (slot (*this, &OptionEditor::focus_out_event_handler), &OptionEditor::raid_path_changed)); + + label = manage(new Label(_("session RAID path"))); + label->set_name ("OptionsLabel"); + path_table.attach (*label, 0, 1, 0, 1, 0, 0); + path_table.attach (session_raid_entry, 1, 3, 0, 1, GTK_FILL|GTK_EXPAND, 0); + + label = manage(new Label(_("Native Format"))); + label->set_name ("OptionsLabel"); + path_table.attach (*label, 0, 1, 1, 2, 0, 0); + path_table.attach (native_format_combo, 1, 3, 1, 2, GTK_FILL|GTK_EXPAND, 0); + + vector nfstrings = internationalize (native_format_strings); + + native_format_combo.set_popdown_strings (nfstrings), + native_format_combo.get_entry()->set_editable (false); + native_format_combo.get_entry()->set_name ("OptionsEntry"); + native_format_combo.set_use_arrows_always (true); + native_format_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::native_format_chosen)); + + fixup_combo_size (native_format_combo, nfstrings); + + if (Config->get_native_format_is_bwf()) { + native_format_combo.get_entry()->set_text (native_format_strings[0]); + } else { + native_format_combo.get_entry()->set_text (native_format_strings[1]); + } + + path_table.show_all(); +} + +void +OptionEditor::add_session_paths () +{ + click_path_entry.set_sensitive (true); + click_emphasis_path_entry.set_sensitive (true); + session_raid_entry.set_sensitive (true); + + if (session->click_sound.length() == 0) { + click_path_entry.set_text (_("internal")); + } else { + click_path_entry.set_text (session->click_sound); + } + + if (session->click_emphasis_sound.length() == 0) { + click_emphasis_path_entry.set_text (_("internal")); + } else { + click_emphasis_path_entry.set_text (session->click_emphasis_sound); + } + + session_raid_entry.set_text(session->raid_path()); +} + +void +OptionEditor::setup_fade_options () +{ + Gtk::HBox* hbox; + vector dumb; + + auto_xfade_button.set_name ("OptionEditorToggleButton"); + xfade_active_button.set_name ("OptionEditorToggleButton"); + + hbox = manage (new HBox); + hbox->set_border_width (12); + hbox->pack_start (auto_xfade_button, false, false); + fade_packer.pack_start (*hbox, false, false); + + hbox = manage (new HBox); + hbox->set_border_width (12); + hbox->pack_start (xfade_active_button, false, false); + fade_packer.pack_start (*hbox, false, false); + + layer_mode_strings = internationalize (lmode_strings); + + dumb.push_back (lmode_strings[Session::LaterHigher]); + dumb.push_back (lmode_strings[Session::MoveAddHigher]); + dumb.push_back (lmode_strings[Session::AddHigher]); + layer_mode_combo.set_popdown_strings (dumb); + + layer_mode_combo.set_use_arrows_always (true); + layer_mode_combo.set_value_in_list (true, false); + layer_mode_combo.get_entry()->set_editable (false); + layer_mode_combo.get_entry()->set_name ("OptionsEntry"); + layer_mode_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::layer_mode_chosen)); + + fixup_combo_size (layer_mode_combo, layer_mode_strings); + + hbox = manage (new HBox); + hbox->set_border_width (5); + hbox->set_spacing (10); + hbox->pack_start (layer_mode_label, false, false); + hbox->pack_start (layer_mode_combo, false, false); + fade_packer.pack_start (*hbox, false, false); + + xfade_model_strings = internationalize (xfl_strings); + + dumb.clear (); + dumb.push_back (xfade_model_strings[FullCrossfade]); + dumb.push_back (xfade_model_strings[ShortCrossfade]); + xfade_model_combo.set_popdown_strings (dumb); + + xfade_model_combo.set_use_arrows_always (true); + xfade_model_combo.set_value_in_list (true, false); + xfade_model_combo.get_entry()->set_editable (false); + xfade_model_combo.get_entry()->set_name ("OptionsEntry"); + xfade_model_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::xfade_model_chosen)); + + fixup_combo_size (xfade_model_combo, xfade_model_strings); + + hbox = manage (new HBox); + hbox->set_border_width (5); + hbox->set_spacing (10); + hbox->pack_start (xfade_model_label, false, false); + hbox->pack_start (xfade_model_combo, false, false); + fade_packer.pack_start (*hbox, false, false); + + auto_xfade_button.set_active (Config->get_auto_xfade()); + /* xfade and layer mode active requires session */ + + auto_xfade_button.clicked.connect (slot (*this, &OptionEditor::auto_xfade_clicked)); + xfade_active_button.clicked.connect (slot (*this, &OptionEditor::xfade_active_clicked)); + + Label* short_xfade_label = manage (new Label (_("Short crossfade length (msecs)"))); + short_xfade_label->set_name ("OptionsLabel"); + + hbox = manage (new HBox); + hbox->set_border_width (5); + hbox->set_spacing (10); + hbox->pack_start (*short_xfade_label, false, false); + hbox->pack_start (short_xfade_slider, true, true); + fade_packer.pack_start (*hbox, false, false); + + short_xfade_adjustment.value_changed.connect (slot (*this, &OptionEditor::short_xfade_adjustment_changed)); + + fade_packer.show_all (); +} + +void +OptionEditor::short_xfade_adjustment_changed () +{ + if (session) { + float val = short_xfade_adjustment.get_value(); + + /* val is in msecs */ + + Crossfade::set_short_xfade_length ((jack_nframes_t) floor (session->frame_rate() * (val / 1000.0))); + } +} + +gint +OptionEditor::layer_mode_chosen (GdkEventAny* ev) +{ + if (!session) { + return FALSE; + } + + string which = layer_mode_combo.get_entry()->get_text (); + + if (which == layer_mode_strings[Session::LaterHigher]) { + session->set_layer_model (Session::LaterHigher); + } else if (which == layer_mode_strings[Session::MoveAddHigher]) { + session->set_layer_model (Session::MoveAddHigher); + } else if (which == layer_mode_strings[Session::AddHigher]) { + session->set_layer_model (Session::AddHigher); + } + return FALSE; +} + +gint +OptionEditor::xfade_model_chosen (GdkEventAny* ev) +{ + if (!session) { + return FALSE; + } + + string which = xfade_model_combo.get_entry()->get_text (); + + if (which == xfade_model_strings[FullCrossfade]) { + session->set_xfade_model (FullCrossfade); + } else if (which == xfade_model_strings[ShortCrossfade]) { + session->set_xfade_model (ShortCrossfade); + } + return FALSE; +} + +void +OptionEditor::auto_xfade_clicked () +{ + Config->set_auto_xfade (auto_xfade_button.get_active()); +} + +void +OptionEditor::xfade_active_clicked () +{ + if (session) { + session->set_crossfades_active (xfade_active_button.get_active()); + } +} + +void +OptionEditor::setup_solo_options () +{ + Gtk::HBox* hbox; + + solo_via_bus_button.set_name ("OptionEditorToggleButton"); + solo_latched_button.set_name ("OptionEditorToggleButton"); + + hbox = manage (new HBox); + hbox->set_border_width (12); + hbox->pack_start (solo_via_bus_button, false, false); + solo_packer.pack_start (*hbox, false, false); + + hbox = manage (new HBox); + hbox->set_border_width (12); + hbox->pack_start (solo_latched_button, false, false); + solo_packer.pack_start (*hbox, false, false); + + solo_via_bus_button.clicked.connect + (slot (*this, &OptionEditor::solo_via_bus_clicked)); + solo_latched_button.clicked.connect + (slot (*this, &OptionEditor::solo_latched_clicked)); + + solo_packer.show_all (); +} + +void +OptionEditor::solo_via_bus_clicked () +{ + if (!session) { + return; + } + + if (solo_via_bus_button.get_active()) { + session->set_solo_model (Session::SoloBus); + } else { + session->set_solo_model (Session::InverseMute); + } +} + +void +OptionEditor::solo_latched_clicked () +{ + if (!session) { + return; + } + + bool x = solo_latched_button.get_active(); + + if (x != session->solo_latched()) { + session->set_solo_latched (x); + } +} + +void +OptionEditor::setup_display_options () +{ + HBox* hbox; + vector dumb; + + display_packer.set_border_width (12); + display_packer.set_spacing (5); + + show_waveforms_button.set_name ("OptionEditorToggleButton"); + show_waveforms_recording_button.set_name ("OptionEditorToggleButton"); + show_measures_button.set_name ("OptionEditorToggleButton"); + follow_playhead_button.set_name ("OptionEditorToggleButton"); + mixer_strip_width_button.set_name ("OptionEditorToggleButton"); + + mixer_strip_width_button.set_active (mixer.get_strip_width() == Narrow); + + hbox = manage (new HBox); + hbox->set_border_width (8); + hbox->pack_start (show_waveforms_button, false, false); + display_packer.pack_start (*hbox, false, false); + + hbox = manage (new HBox); + hbox->set_border_width (8); + hbox->pack_start (show_waveforms_recording_button, false, false); + display_packer.pack_start (*hbox, false, false); + + hbox = manage (new HBox); + hbox->set_border_width (8); + hbox->pack_start (show_measures_button, false, false); + display_packer.pack_start (*hbox, false, false); + + hbox = manage (new HBox); + hbox->set_border_width (8); + hbox->pack_start (mixer_strip_width_button, false, false); + display_packer.pack_start (*hbox, false, false); + + hbox = manage (new HBox); + hbox->set_border_width (8); + hbox->pack_start (follow_playhead_button, false, false); + display_packer.pack_start (*hbox, false, false); + + Label *meter_hold_label = manage (new Label (_("Meter Peak Hold"))); + meter_hold_label->set_name ("OptionsLabel"); + dumb.clear (); + dumb.push_back (_("Off")); + dumb.push_back (_("Short")); + dumb.push_back (_("Medium")); + dumb.push_back (_("Long")); + meter_hold_combo.set_popdown_strings (dumb); + meter_hold_combo.set_use_arrows_always (true); + meter_hold_combo.set_value_in_list (true, false); + meter_hold_combo.get_entry()->set_editable (false); + meter_hold_combo.get_entry()->set_name ("OptionsEntry"); + meter_hold_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::meter_hold_chosen)); + hbox = manage (new HBox); + hbox->set_border_width (8); + hbox->set_spacing (8); + hbox->pack_start (*meter_hold_label, false, false); + hbox->pack_start (meter_hold_combo, false, false); + display_packer.pack_start (*hbox, false, false); + + Label *meter_falloff_label = manage (new Label (_("Meter Falloff"))); + meter_falloff_label->set_name ("OptionsLabel"); + dumb.clear (); + dumb.push_back (_("Off")); + dumb.push_back (_("Slowest")); + dumb.push_back (_("Slow")); + dumb.push_back (_("Medium")); + dumb.push_back (_("Fast")); + dumb.push_back (_("Faster")); + dumb.push_back (_("Fastest")); + meter_falloff_combo.set_popdown_strings (dumb); + meter_falloff_combo.set_use_arrows_always (true); + meter_falloff_combo.set_value_in_list (true, false); + meter_falloff_combo.get_entry()->set_editable (false); + meter_falloff_combo.get_entry()->set_name ("OptionsEntry"); + meter_falloff_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::meter_falloff_chosen)); + hbox = manage (new HBox); + hbox->set_border_width (8); + hbox->set_spacing (8); + hbox->pack_start (*meter_falloff_label, false, false); + hbox->pack_start (meter_falloff_combo, false, false); + display_packer.pack_start (*hbox, false, false); + + + show_waveforms_button.clicked.connect (slot (*this, &OptionEditor::show_waveforms_clicked)); + show_waveforms_recording_button.clicked.connect (slot (*this, &OptionEditor::show_waveforms_recording_clicked)); + show_measures_button.clicked.connect (slot (*this, &OptionEditor::show_measures_clicked)); + mixer_strip_width_button.clicked.connect (slot (*this, &OptionEditor::strip_width_clicked)); + follow_playhead_button.clicked.connect (slot (*this, &OptionEditor::follow_playhead_clicked)); + + editor.DisplayControlChanged.connect (slot (*this, &OptionEditor::display_control_changed)); + + show_measures_button.set_active (editor.show_measures()); + show_waveforms_button.set_active (editor.show_waveforms()); + show_waveforms_recording_button.set_active (editor.show_waveforms_recording()); + follow_playhead_button.set_active (editor.follow_playhead()); +} + +gint +OptionEditor::meter_hold_chosen (GdkEventAny* ev) +{ + if (session) { + string str = meter_hold_combo.get_entry()->get_text(); + + if (str == _("Off")) { + session->set_meter_hold (0); + } else if (str == _("Short")) { + session->set_meter_hold (40); + } else if (str == _("Medium")) { + session->set_meter_hold (100); + } else if (str == _("Long")) { + session->set_meter_hold (200); + } + } + + return TRUE; +} + +gint +OptionEditor::meter_falloff_chosen (GdkEventAny* ev) +{ + if (session) { + string str = meter_falloff_combo.get_entry()->get_text(); + + if (str == _("Off")) { + session->set_meter_falloff (0.0f); + } else if (str == _("Slowest")) { + session->set_meter_falloff (0.266f); // 6.6 dB/sec falloff at update rate of 40 ms + } else if (str == _("Slow")) { + session->set_meter_falloff (0.342f); // 8.6 dB/sec falloff at update rate of 40 ms + } else if (str == _("Medium")) { + session->set_meter_falloff (0.7f); + } else if (str == _("Fast")) { + session->set_meter_falloff (1.1f); + } else if (str == _("Faster")) { + session->set_meter_falloff (1.5f); + } else if (str == _("Fastest")) { + session->set_meter_falloff (2.5f); + } + } + + return TRUE; +} + +void +OptionEditor::display_control_changed (Editing::DisplayControl dc) +{ + ToggleButton* button = 0; + bool val = true; + + switch (dc) { + case ShowMeasures: + val = editor.show_measures (); + button = &show_measures_button; + break; + case ShowWaveforms: + val = editor.show_waveforms (); + button = &show_waveforms_button; + break; + case ShowWaveformsRecording: + val = editor.show_waveforms_recording (); + button = &show_waveforms_recording_button; + break; + case FollowPlayhead: + val = editor.follow_playhead (); + button = &follow_playhead_button; + break; + } + + if (button->get_active() != val) { + button->set_active (val); + } +} + +void +OptionEditor::setup_sync_options () +{ + Label *slave_type_label = manage (new Label (_("Positional Sync"))); + HBox* hbox; + vector dumb; + + slave_type_label->set_name("OptionsLabel"); + positional_sync_strings = internationalize (psync_strings); + + slave_type_combo.set_use_arrows_always (true); + slave_type_combo.set_value_in_list (true, false); + slave_type_combo.get_entry()->set_editable (false); + slave_type_combo.get_entry()->set_name ("OptionsEntry"); + slave_type_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::slave_type_chosen)); + + dumb.clear (); + dumb.push_back (X_("24 FPS")); + dumb.push_back (X_("25 FPS")); + dumb.push_back (X_("30 FPS drop")); + dumb.push_back (X_("30 FPS non-drop")); + + smpte_fps_combo.set_popdown_strings (dumb); + smpte_fps_combo.set_use_arrows_always (true); + smpte_fps_combo.set_value_in_list (true, false); + smpte_fps_combo.get_entry()->set_editable (false); + smpte_fps_combo.get_entry()->set_name ("OptionsEntry"); + smpte_fps_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::smpte_fps_chosen)); + + smpte_offset_clock.set_mode (AudioClock::SMPTE); + smpte_offset_clock.ValueChanged.connect (slot (*this, &OptionEditor::smpte_offset_chosen)); + + send_mtc_button.set_name ("OptionEditorToggleButton"); + jack_time_master_button.set_name ("OptionEditorToggleButton"); + smpte_offset_negative_button.set_name ("OptionEditorToggleButton"); + + send_mtc_button.unset_flags (GTK_CAN_FOCUS); + jack_time_master_button.unset_flags (GTK_CAN_FOCUS); + smpte_offset_negative_button.unset_flags (GTK_CAN_FOCUS); + + hbox = manage (new HBox); + hbox->set_border_width (5); + hbox->set_spacing (10); + hbox->pack_start (*slave_type_label, false, false); + hbox->pack_start (slave_type_combo, false, false); + + sync_packer.pack_start (*hbox, false, false); + + hbox = manage (new HBox); + hbox->set_border_width (5); + hbox->pack_start (send_mtc_button, false, false); + sync_packer.pack_start (*hbox, false, false); + + hbox = manage (new HBox); + hbox->set_border_width (5); + hbox->pack_start (jack_time_master_button, false, false); + sync_packer.pack_start (*hbox, false, false); + + Label *smpte_fps_label = manage (new Label (_("SMPTE Frames/second"))); + Label *smpte_offset_label = manage (new Label (_("SMPTE Offset"))); + smpte_fps_label->set_name("OptionsLabel"); + smpte_offset_label->set_name("OptionsLabel"); + + hbox = manage (new HBox); + hbox->set_border_width (5); + hbox->set_spacing (10); + hbox->pack_start (*smpte_fps_label, false, false); + hbox->pack_start (smpte_fps_combo, false, false); + + sync_packer.pack_start (*hbox, false, false); + + hbox = manage (new HBox); + hbox->set_border_width (5); + hbox->set_spacing (10); + hbox->pack_start (*smpte_offset_label, false, false); + hbox->pack_start (smpte_offset_clock, false, false); + hbox->pack_start (smpte_offset_negative_button, false, false); + + sync_packer.pack_start (*hbox, false, false); + + jack_time_master_button.set_active (Config->get_jack_time_master()); + + send_mtc_button.button_press_event.connect (bind (slot (*this, &OptionEditor::send_mtc_toggled), &send_mtc_button)); + jack_time_master_button.clicked.connect (slot (*this, &OptionEditor::jack_time_master_clicked)); + smpte_offset_negative_button.clicked.connect (slot (*this, &OptionEditor::smpte_offset_negative_clicked)); +} + +void +OptionEditor::smpte_offset_negative_clicked () +{ + if (session) { + session->set_smpte_offset_negative (smpte_offset_negative_button.get_active()); + } +} + +gint +OptionEditor::smpte_fps_chosen (GdkEventAny* ev) +{ + if (session) { + string str = smpte_fps_combo.get_entry()->get_text(); + + if (str == X_("24 FPS")) { + session->set_smpte_type (24.0, false); + } else if (str == X_("25 FPS")) { + session->set_smpte_type (25.0, false); + } else if (str == X_("30 FPS drop")) { + session->set_smpte_type (29.97, true); + } else if (str == X_("30 FPS non-drop")) { + session->set_smpte_type (30.0, false); + } + } + + return TRUE; +} + +void +OptionEditor::smpte_offset_chosen() +{ + if (session) { + jack_nframes_t frames = smpte_offset_clock.current_duration(); + session->set_smpte_offset (frames); + } +} + + +void +OptionEditor::setup_midi_options () +{ + HBox* hbox; + MIDI::Manager::PortMap::const_iterator i; + const MIDI::Manager::PortMap& ports = MIDI::Manager::instance()->get_midi_ports(); + int n; + ToggleButton* tb; + RadioButton* rb; + RadioButton* first_mtc_button = 0; + RadioButton* first_mmc_button = 0; + RadioButton* first_midi_button = 0; + + Gtk::Table* table = manage (new Table (ports.size() + 4, 9)); + + table->set_row_spacings (6); + table->set_col_spacings (10); + + table->attach (*(manage (new Label (X_("Port")))), 0, 1, 0, 1); + table->attach (*(manage (new Label (X_("Offline")))), 1, 2, 0, 1); + table->attach (*(manage (new Label (X_("Trace\nInput")))), 2, 3, 0, 1); + table->attach (*(manage (new Label (X_("Trace\nOutput")))), 3, 4, 0, 1); + table->attach (*(manage (new Label (X_("MTC")))), 4, 5, 0, 1); + table->attach (*(manage (new Label (X_("MMC")))), 6, 7, 0, 1); + table->attach (*(manage (new Label (X_("MIDI Parameter\nControl")))), 8, 9, 0, 1); + + table->attach (*(manage (new HSeparator())), 0, 9, 1, 2); + table->attach (*(manage (new VSeparator())), 5, 6, 0, 8); + table->attach (*(manage (new VSeparator())), 7, 8, 0, 8); + + for (n = 0, i = ports.begin(); i != ports.end(); ++n, ++i) { + + pair > newpair; + + newpair.first = i->second; + + table->attach (*(manage (new Label (i->first))), 0, 1, n+2, n+3, 0, 0); + tb = manage (new ToggleButton (_("online"))); + tb->set_name ("OptionEditorToggleButton"); + + /* remember, we have to handle the i18n case where the relative + lengths of the strings in language N is different than in english. + */ + + if (strlen (_("offline")) > strlen (_("online"))) { + set_usize_to_display_given_text (*tb, _("offline"), 15, 12); + } else { + set_usize_to_display_given_text (*tb, _("online"), 15, 12); + } + + tb->set_active (!(*i).second->input()->offline()); + tb->button_press_event.connect (bind (slot (*this, &OptionEditor::port_online_toggled), (*i).second, tb)); + (*i).second->input()->OfflineStatusChanged.connect (bind (slot (*this, &OptionEditor::map_port_online), (*i).second, tb)); + table->attach (*tb, 1, 2, n+2, n+3, 0, 0); + + tb = manage (new ToggleButton ()); + tb->set_name ("OptionEditorToggleButton"); + tb->button_press_event.connect (bind (slot (*this, &OptionEditor::port_trace_in_toggled), (*i).second, tb)); + tb->set_usize (10, 10); + table->attach (*tb, 2, 3, n+2, n+3, 0, 0); + + tb = manage (new ToggleButton ()); + tb->set_name ("OptionEditorToggleButton"); + tb->button_press_event.connect (bind (slot (*this, &OptionEditor::port_trace_out_toggled), (*i).second, tb)); + tb->set_usize (10, 10); + table->attach (*tb, 3, 4, n+2, n+3, 0, 0); + + rb = manage (new RadioButton ()); + newpair.second.push_back (rb); + rb->set_name ("OptionEditorToggleButton"); + if (n == 0) { + first_mtc_button = rb; + } else { + rb->set_group (first_mtc_button->group()); + } + table->attach (*rb, 4, 5, n+2, n+3, 0, 0); + rb->button_press_event.connect (bind (slot (*this, &OptionEditor::mtc_port_chosen), (*i).second, rb)); + + if (Config->get_mtc_port_name() == i->first) { + rb->set_active (true); + } + + rb = manage (new RadioButton ()); + newpair.second.push_back (rb); + rb->set_name ("OptionEditorToggleButton"); + if (n == 0) { + first_mmc_button = rb; + } else { + rb->set_group (first_mmc_button->group()); + } + table->attach (*rb, 6, 7, n+2, n+3, 0, 0); + rb->button_press_event.connect (bind (slot (*this, &OptionEditor::mmc_port_chosen), (*i).second, rb)); + + if (Config->get_mmc_port_name() == i->first) { + rb->set_active (true); + } + + rb = manage (new RadioButton ()); + newpair.second.push_back (rb); + rb->set_name ("OptionEditorToggleButton"); + if (n == 0) { + first_midi_button = rb; + } else { + rb->set_group (first_midi_button->group()); + } + table->attach (*rb, 8, 9, n+2, n+3, 0, 0); + rb->button_press_event.connect (bind (slot (*this, &OptionEditor::midi_port_chosen), (*i).second, rb)); + + if (Config->get_midi_port_name() == i->first) { + rb->set_active (true); + } + + port_toggle_buttons.insert (newpair); + } + + table->show_all (); + + hbox = manage (new HBox); + hbox->set_border_width (6); + hbox->pack_start (*table, true, false); + midi_packer.pack_start (*hbox, false, false); + + VBox* mmcbuttonbox = manage (new VBox); + + mmc_control_button.set_name ("OptionEditorToggleButton"); + + hbox = manage (new HBox); + hbox->set_border_width (6); + hbox->pack_start (mmc_control_button, false, false, 36); + mmcbuttonbox->pack_start (*hbox, false, false); + + midi_control_button.set_name ("OptionEditorToggleButton"); + + hbox = manage (new HBox); + hbox->set_border_width (6); + hbox->pack_start (midi_control_button, false, false, 36); + mmcbuttonbox->pack_start (*hbox, false, false); + + send_mmc_button.set_name ("OptionEditorToggleButton"); + + hbox = manage (new HBox); + hbox->set_border_width (6); + hbox->pack_start (send_mmc_button, false, false, 36); + mmcbuttonbox->pack_start (*hbox, false, false); + + midi_feedback_button.set_name ("OptionEditorToggleButton"); + + hbox = manage (new HBox); + hbox->set_border_width (6); + hbox->pack_start (midi_feedback_button, false, false, 36); + mmcbuttonbox->pack_start (*hbox, false, false); + + midi_packer.pack_start (*mmcbuttonbox, false, false); + + mmc_control_button.toggled.connect (bind (slot (*this, &OptionEditor::mmc_control_toggled), &mmc_control_button)); + midi_control_button.toggled.connect (bind (slot (*this, &OptionEditor::midi_control_toggled), &midi_control_button)); + send_mmc_button.toggled.connect (bind (slot (*this, &OptionEditor::send_mmc_toggled), &send_mmc_button)); + midi_feedback_button.toggled.connect (bind (slot (*this, &OptionEditor::midi_feedback_toggled), &midi_feedback_button)); +} + +gint +OptionEditor::mtc_port_chosen (GdkEventButton* ev, MIDI::Port *port, Gtk::RadioButton* rb) +{ + if (session) { + if (!rb->get_active()) { + if (port) { + session->set_mtc_port (port->name()); + Config->set_mtc_port_name (port->name()); + } else { + session->set_mtc_port (""); + } + + /* update sync options to reflect MTC port availability */ + + vector dumb; + dumb.push_back (positional_sync_strings[Session::None]); + dumb.push_back (positional_sync_strings[Session::JACK]); + + if (session->mtc_port()) { + dumb.push_back (positional_sync_strings[Session::MTC]); + } + slave_type_combo.set_popdown_strings (dumb); + + rb->set_active (true); + } + } + + return stop_signal (*rb, "button_press_event"); +} + +gint +OptionEditor::mmc_port_chosen (GdkEventButton* ev, MIDI::Port* port, Gtk::RadioButton* rb) +{ + if (session) { + if (!rb->get_active()) { + if (port) { + session->set_mmc_port (port->name()); + Config->set_mtc_port_name (port->name()); + } else { + session->set_mmc_port (""); + } + rb->set_active (true); + } + } + return stop_signal (*rb, "button_press_event"); +} + +gint +OptionEditor::midi_port_chosen (GdkEventButton* ev, MIDI::Port* port, Gtk::RadioButton* rb) +{ + if (session) { + if (!rb->get_active()) { + if (port) { + session->set_midi_port (port->name()); + Config->set_midi_port_name (port->name()); + } else { + session->set_midi_port (""); + } + rb->set_active (true); + } + } + return stop_signal (*rb, "button_press_event"); +} + +gint +OptionEditor::port_online_toggled (GdkEventButton* ev, MIDI::Port* port, ToggleButton* tb) +{ + bool wanted = tb->get_active(); /* it hasn't changed at this point */ + + if (wanted != port->input()->offline()) { + port->input()->set_offline (wanted); + } + return stop_signal (*tb, "button_press_event"); +} + +void +OptionEditor::map_port_online (MIDI::Port* port, ToggleButton* tb) +{ + if (port->input()->offline()) { + static_cast(tb->get_child())->set_text (_("offline")); + tb->set_active (false); + } else { + static_cast(tb->get_child())->set_text (_("online")); + tb->set_active (true); + } +} + +gint +OptionEditor::port_trace_in_toggled (GdkEventButton* ev, MIDI::Port* port, ToggleButton* tb) +{ + /* XXX not very good MVC style here */ + + port->input()->trace (!tb->get_active(), &cerr, string (port->name()) + string (" input: ")); + tb->set_active (!tb->get_active()); + return stop_signal (*tb, "button_press_event"); +} + +gint +OptionEditor::port_trace_out_toggled (GdkEventButton* ev,MIDI::Port* port, ToggleButton* tb) +{ + /* XXX not very good MVC style here */ + + port->output()->trace (!tb->get_active(), &cerr, string (port->name()) + string (" output: ")); + tb->set_active (!tb->get_active()); + return stop_signal (*tb, "button_press_event"); +} + +gint +OptionEditor::send_mtc_toggled (GdkEventButton *ev, CheckButton *button) +{ + if (session) { + session->set_send_mtc (!button->get_active()); + } + return stop_signal (*button, "button_press_event"); +} + +void +OptionEditor::send_mmc_toggled (CheckButton *button) +{ + if (session) { + session->set_send_mmc (button->get_active()); + } +} + +void +OptionEditor::mmc_control_toggled (CheckButton *button) +{ + if (session) { + session->set_mmc_control (button->get_active()); + } +} + +void +OptionEditor::midi_control_toggled (CheckButton *button) +{ + if (session) { + session->set_midi_control (button->get_active()); + } +} + +void +OptionEditor::midi_feedback_toggled (CheckButton *button) +{ + if (session) { + session->set_midi_feedback (button->get_active()); + } +} + +void +OptionEditor::save () +{ + /* XXX a bit odd that we save the entire session state here */ + + ui.save_state (""); +} + +gint +OptionEditor::wm_close (GdkEventAny *ev) +{ + save (); + just_close_win(); + return TRUE; +} + +void +OptionEditor::jack_time_master_clicked () +{ + bool yn = jack_time_master_button.get_active(); + + Config->set_jack_time_master (yn); + + if (session) { + session->engine().reset_timebase (); + } +} + +void +OptionEditor::raid_path_changed () +{ + if (session) { + session->set_raid_path (session_raid_entry.get_text()); + } +} + +void +OptionEditor::click_browse_clicked () +{ + SoundFileSelector& sfdb (ARDOUR_UI::instance()->get_sfdb_window()); + SigC::Connection c = sfdb.Action.connect (slot (*this, &OptionEditor::click_chosen)); + + sfdb.run (_("Use as click"), false, true); + c.disconnect (); +} + +void +OptionEditor::click_chosen (vector paths, bool ignore) +{ + string path; + + if (!paths.empty()) { + path = paths.front(); + } else { + return; + } + + click_path_entry.set_text (path); + click_sound_changed (); +} + +void +OptionEditor::click_emphasis_browse_clicked () +{ + SoundFileSelector& sfdb (ARDOUR_UI::instance()->get_sfdb_window()); + SigC::Connection c = sfdb.Action.connect (slot (*this, &OptionEditor::click_emphasis_chosen)); + + sfdb.run (_("Use as click emphasis"), false, true); + c.disconnect (); + +} + +void +OptionEditor::click_emphasis_chosen (vector paths, bool ignore) +{ + string path; + + if (!paths.empty()) { + path = paths.front(); + } else { + return; + } + + click_emphasis_path_entry.set_text (path); + click_emphasis_sound_changed (); +} + +void +OptionEditor::click_sound_changed () +{ + if (session) { + string path = click_path_entry.get_text(); + + if (path == session->click_sound) { + return; + } + + if (path.length() == 0) { + + session->set_click_sound (""); + + } else { + + strip_whitespace_edges (path); + + if (path == _("internal")) { + session->set_click_sound (""); + } else { + session->set_click_sound (path); + } + } + } +} + +void +OptionEditor::click_emphasis_sound_changed () +{ + if (session) { + string path = click_emphasis_path_entry.get_text(); + + if (path == session->click_emphasis_sound) { + return; + } + + if (path.length() == 0) { + + session->set_click_emphasis_sound (""); + + } else { + + strip_whitespace_edges (path); + + if (path == _("internal")) { + session->set_click_emphasis_sound (""); + } else { + session->set_click_emphasis_sound (path); + } + } + } +} + +void +OptionEditor::show_waveforms_clicked () +{ + editor.set_show_waveforms (show_waveforms_button.get_active()); +} + +void +OptionEditor::show_waveforms_recording_clicked () +{ + editor.set_show_waveforms_recording (show_waveforms_recording_button.get_active()); +} + +void +OptionEditor::show_measures_clicked () +{ + editor.set_show_measures (show_measures_button.get_active()); +} + +void +OptionEditor::follow_playhead_clicked () +{ + editor.set_follow_playhead (follow_playhead_button.get_active()); +} + +void +OptionEditor::strip_width_clicked () +{ + mixer.set_strip_width (mixer_strip_width_button.get_active() ? Narrow : Wide); +} + + +void +OptionEditor::just_close_win() +{ + hide_all(); + ARDOUR_UI::instance()->allow_focus(false); +} + +void +OptionEditor::queue_session_control_changed (Session::ControlType t) +{ + ui.call_slot (bind (slot (*this, &OptionEditor::session_control_changed), t)); +} + +void +OptionEditor::session_control_changed (Session::ControlType t) +{ + switch (t) { + case Session::SlaveType: + switch (session->slave_source()) { + case Session::None: + slave_type_combo.get_entry()->set_text (positional_sync_strings[Session::None]); + break; + case Session::MTC: + slave_type_combo.get_entry()->set_text (positional_sync_strings[Session::MTC]); + break; + case Session::JACK: + slave_type_combo.get_entry()->set_text (positional_sync_strings[Session::JACK]); + break; + default: + slave_type_combo.get_entry()->set_text (_("--unknown--")); + break; + } + + break; + + case Session::SendMTC: + map_some_session_state (send_mtc_button, &Session::get_send_mtc); + break; + + case Session::SendMMC: + map_some_session_state (send_mmc_button, &Session::get_send_mmc); + break; + + case Session::MMCControl: + map_some_session_state (mmc_control_button, &Session::get_mmc_control); + break; + + case Session::MidiFeedback: + map_some_session_state (midi_feedback_button, &Session::get_midi_feedback); + break; + + case Session::MidiControl: + map_some_session_state (midi_control_button, &Session::get_midi_control); + break; + + default: + break; + } +} + +gint +OptionEditor::native_format_chosen (GdkEventAny *ignored) +{ + string which; + + if (session == 0) { + return FALSE; + } + + bool use_bwf = (native_format_combo.get_entry()->get_text() == native_format_strings[0]); + + if (use_bwf != Config->get_native_format_is_bwf()) { + Config->set_native_format_is_bwf (use_bwf); + session->reset_native_file_format (); + } + + return TRUE; +} + +gint +OptionEditor::slave_type_chosen (GdkEventAny *ignored) +{ + string which; + + if (session == 0) { + return FALSE; + } + + which = slave_type_combo.get_entry()->get_text(); + + if (which == positional_sync_strings[Session::None]) { + session->request_slave_source (Session::None); + } else if (which == positional_sync_strings[Session::MTC]) { + session->request_slave_source (Session::MTC); + } else if (which == positional_sync_strings[Session::JACK]) { + session->request_slave_source (Session::JACK); + } + return FALSE; +} + +void +OptionEditor::clear_click_editor () +{ + if (click_io_selector) { + click_packer.remove (*click_io_selector); + click_packer.remove (*click_gpm); + delete click_io_selector; + delete click_gpm; + click_io_selector = 0; + click_gpm = 0; + } +} + +void +OptionEditor::setup_click_editor () +{ + Label* label; + HBox* hpacker = manage (new HBox); + + click_path_entry.set_sensitive (true); + click_emphasis_path_entry.set_sensitive (true); + + click_path_entry.set_name ("OptionsEntry"); + click_emphasis_path_entry.set_name ("OptionsEntry"); + + click_path_entry.activate.connect (slot (*this, &OptionEditor::click_sound_changed)); + click_emphasis_path_entry.activate.connect (slot (*this, &OptionEditor::click_emphasis_sound_changed)); + + click_path_entry.focus_in_event.connect (slot (Keyboard::the_keyboard(), &Keyboard::focus_in_handler)); + click_path_entry.focus_out_event.connect (bind (slot (*this, &OptionEditor::focus_out_event_handler), &OptionEditor::click_sound_changed)); + click_emphasis_path_entry.focus_in_event.connect (slot (Keyboard::the_keyboard(), &Keyboard::focus_in_handler)); + click_emphasis_path_entry.focus_out_event.connect (bind (slot (*this, &OptionEditor::focus_out_event_handler), &OptionEditor::click_emphasis_sound_changed)); + + click_browse_button.set_name ("EditorGTKButton"); + click_emphasis_browse_button.set_name ("EditorGTKButton"); + click_browse_button.clicked.connect (slot (*this, &OptionEditor::click_browse_clicked)); + click_emphasis_browse_button.clicked.connect (slot (*this, &OptionEditor::click_emphasis_browse_clicked)); + + click_packer.set_border_width (12); + click_packer.set_spacing (5); + + click_io_selector = new IOSelector (*session, session->click_io(), false); + click_gpm = new GainMeter (session->click_io(), *session); + + click_table.set_col_spacings (10); + + label = manage(new Label(_("Click audio file"))); + label->set_name ("OptionsLabel"); + click_table.attach (*label, 0, 1, 0, 1, 0, 0); + click_table.attach (click_path_entry, 1, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0); + click_table.attach (click_browse_button, 2, 3, 0, 1, 0, 0); + + label = manage(new Label(_("Click emphasis audiofile"))); + label->set_name ("OptionsLabel"); + click_table.attach (*label, 0, 1, 1, 2, 0, 0); + click_table.attach (click_emphasis_path_entry, 1, 2, 1, 2, GTK_FILL|GTK_EXPAND, 0); + click_table.attach (click_emphasis_browse_button, 2, 3, 1, 2, 0, 0); + + hpacker->set_spacing (10); + hpacker->pack_start (*click_io_selector, false, false); + hpacker->pack_start (*click_gpm, false, false); + + click_packer.pack_start (click_table, false, false); + click_packer.pack_start (*hpacker, false, false); + + click_packer.show_all (); +} + +void +OptionEditor::clear_auditioner_editor () +{ + if (auditioner_io_selector) { + audition_hpacker.remove (*auditioner_io_selector); + audition_hpacker.remove (*auditioner_gpm); + delete auditioner_io_selector; + delete auditioner_gpm; + auditioner_io_selector = 0; + auditioner_gpm = 0; + } +} + +void +OptionEditor::setup_auditioner_editor () +{ + audition_packer.set_border_width (12); + audition_packer.set_spacing (5); + audition_hpacker.set_spacing (10); + + audition_label.set_name ("OptionEditorAuditionerLabel"); + audition_label.set_text (_("The auditioner is a dedicated mixer strip used\n" + "for listening to specific regions outside the context\n" + "of the overall mix. It can be connected just like any\n" + "other mixer strip.")); + + audition_packer.pack_start (audition_label, false, false, 10); + audition_packer.pack_start (audition_hpacker, false, false); +} + +void +OptionEditor::connect_audition_editor () +{ + auditioner_io_selector = new IOSelector (*session, session->the_auditioner(), false); + auditioner_gpm = new GainMeter (session->the_auditioner(), *session); + + audition_hpacker.pack_start (*auditioner_io_selector, false, false); + audition_hpacker.pack_start (*auditioner_gpm, false, false); + + auditioner_io_selector->show_all (); + auditioner_gpm->show_all (); +} + +gint +OptionEditor::focus_out_event_handler (GdkEventFocus* ev, void (OptionEditor::*pmf)()) +{ + (this->*pmf)(); + return Keyboard::the_keyboard().focus_out_handler (ev); +} + +void +OptionEditor::setup_misc_options() +{ + Gtk::Table* table = manage (new Table (4, 2)); + table->set_homogeneous (true); + + misc_packer.set_border_width (8); + misc_packer.set_spacing (3); + misc_packer.pack_start (*table, true, true); + + table->attach (hw_monitor_button, 0, 1, 0, 1, GTK_FILL, 0, 8, 0); + table->attach (sw_monitor_button, 0, 1, 1, 2, GTK_FILL, 0, 8, 0); + table->attach (plugins_stop_button, 0, 1, 2, 3, GTK_FILL, 0, 8, 0); + table->attach (plugins_on_rec_button, 0, 1, 3, 4, GTK_FILL, 0, 8, 0); + table->attach (verify_remove_last_capture_button, 0, 1, 4, 5, GTK_FILL, 0, 8, 0); + + table->attach (stop_rec_on_xrun_button, 1, 2, 0, 1, GTK_FILL, 0, 8, 0); + table->attach (stop_at_end_button, 1, 2, 1, 2, GTK_FILL, 0, 8, 0); + table->attach (debug_keyboard_button, 1, 2, 2, 3, GTK_FILL, 0, 8, 0); + table->attach (speed_quieten_button, 1, 2, 3, 4, GTK_FILL, 0, 8, 0); + + Gtk::VBox* connect_box = manage (new VBox); + connect_box->set_spacing (3); + connect_box->set_border_width (8); + + auto_connect_output_manual_button.set_group (auto_connect_output_master_button.group()); + auto_connect_output_physical_button.set_group (auto_connect_output_master_button.group()); + + Gtk::HBox* useless_box = manage (new HBox); + useless_box->pack_start (auto_connect_inputs_button, false, false); + connect_box->pack_start (*useless_box, false, false); + connect_box->pack_start (auto_connect_output_master_button, false, false); + connect_box->pack_start (auto_connect_output_physical_button, false, false); + connect_box->pack_start (auto_connect_output_manual_button, false); + + misc_packer.pack_start (*connect_box, false, false); + + hw_monitor_button.set_name ("OptionEditorToggleButton"); + sw_monitor_button.set_name ("OptionEditorToggleButton"); + plugins_stop_button.set_name ("OptionEditorToggleButton"); + plugins_on_rec_button.set_name ("OptionEditorToggleButton"); + verify_remove_last_capture_button.set_name ("OptionEditorToggleButton"); + auto_connect_inputs_button.set_name ("OptionEditorToggleButton"); + auto_connect_output_physical_button.set_name ("OptionEditorToggleButton"); + auto_connect_output_master_button.set_name ("OptionEditorToggleButton"); + auto_connect_output_manual_button.set_name ("OptionEditorToggleButton"); + stop_rec_on_xrun_button.set_name ("OptionEditorToggleButton"); + stop_at_end_button.set_name ("OptionEditorToggleButton"); + debug_keyboard_button.set_name ("OptionEditorToggleButton"); + speed_quieten_button.set_name ("OptionEditorToggleButton"); + + hw_monitor_button.set_active (Config->get_use_hardware_monitoring()); + sw_monitor_button.set_active (!Config->get_no_sw_monitoring()); + plugins_stop_button.set_active (Config->get_plugins_stop_with_transport()); + stop_rec_on_xrun_button.set_active (Config->get_stop_recording_on_xrun()); + stop_at_end_button.set_active (Config->get_stop_at_session_end()); + debug_keyboard_button.set_active (false); + speed_quieten_button.set_active (Config->get_quieten_at_speed() != 1.0f); + + hw_monitor_button.clicked.connect (slot (*this, &OptionEditor::hw_monitor_clicked)); + sw_monitor_button.clicked.connect (slot (*this, &OptionEditor::sw_monitor_clicked)); + plugins_stop_button.clicked.connect (slot (*this, &OptionEditor::plugins_stop_with_transport_clicked)); + plugins_on_rec_button.clicked.connect (slot (*this, &OptionEditor::plugins_on_while_recording_clicked)); + verify_remove_last_capture_button.clicked.connect (slot (*this, &OptionEditor::verify_remove_last_capture_clicked)); + auto_connect_inputs_button.clicked.connect (slot (*this, &OptionEditor::auto_connect_inputs_clicked)); + auto_connect_output_physical_button.clicked.connect (slot (*this, &OptionEditor::auto_connect_output_physical_clicked)); + auto_connect_output_master_button.clicked.connect (slot (*this, &OptionEditor::auto_connect_output_master_clicked)); + auto_connect_output_manual_button.clicked.connect (slot (*this, &OptionEditor::auto_connect_output_manual_clicked)); + stop_rec_on_xrun_button.clicked.connect (slot (*this, &OptionEditor::stop_rec_on_xrun_clicked)); + stop_at_end_button.clicked.connect (slot (*this, &OptionEditor::stop_at_end_clicked)); + debug_keyboard_button.clicked.connect (slot (*this, &OptionEditor::debug_keyboard_clicked)); + speed_quieten_button.clicked.connect (slot (*this, &OptionEditor::speed_quieten_clicked)); +} + +void +OptionEditor::speed_quieten_clicked () +{ + if (speed_quieten_button.get_active()) { + Config->set_quieten_at_speed (0.251189); // -12dB reduction for ffwd or rewind + } else { + Config->set_quieten_at_speed (1.0); /* no change */ + } +} + +void +OptionEditor::debug_keyboard_clicked () +{ + extern bool debug_keyboard; + debug_keyboard = debug_keyboard_button.get_active (); +} + +void +OptionEditor::auto_connect_inputs_clicked () +{ + if (session) { + session->set_input_auto_connect (auto_connect_inputs_button.get_active()); + } +} + +void +OptionEditor::auto_connect_output_master_clicked () +{ + if (session) { + if (auto_connect_output_master_button.get_active()) { + session->set_output_auto_connect (Session::AutoConnectMaster); + } + } +} + +void +OptionEditor::auto_connect_output_physical_clicked () +{ + if (session) { + if (auto_connect_output_physical_button.get_active()) { + session->set_output_auto_connect (Session::AutoConnectPhysical); + } + } +} + +void +OptionEditor::auto_connect_output_manual_clicked () +{ + if (session) { + if (auto_connect_output_manual_button.get_active()) { + session->set_output_auto_connect (Session::AutoConnectOption (0)); + } + } +} + +void +OptionEditor::hw_monitor_clicked () +{ + Config->set_use_hardware_monitoring (hw_monitor_button.get_active()); +} + +void +OptionEditor::sw_monitor_clicked () +{ + Config->set_no_sw_monitoring (!sw_monitor_button.get_active()); +} + +void +OptionEditor::plugins_stop_with_transport_clicked () +{ + Config->set_plugins_stop_with_transport (plugins_stop_button.get_active()); +} + +void +OptionEditor::plugins_on_while_recording_clicked () +{ + if (session) { + session->set_recording_plugins (plugins_on_rec_button.get_active()); + } +} + +void +OptionEditor::verify_remove_last_capture_clicked () +{ + Config->set_verify_remove_last_capture(verify_remove_last_capture_button.get_active()); +} + +void +OptionEditor::stop_rec_on_xrun_clicked () +{ + Config->set_stop_recording_on_xrun (stop_rec_on_xrun_button.get_active()); +} + +void +OptionEditor::stop_at_end_clicked () +{ + Config->set_stop_at_session_end (stop_at_end_button.get_active()); +} + +static const struct { + const char *name; + guint modifier; +} modifiers[] = { + { "Shift", GDK_SHIFT_MASK }, + { "Control", GDK_CONTROL_MASK }, + { "Alt (Mod1)", GDK_MOD1_MASK }, + { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK }, + { "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK }, + { "Shift-Alt", GDK_SHIFT_MASK|GDK_MOD1_MASK }, + { "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK }, + { "Mod2", GDK_MOD2_MASK }, + { "Mod3", GDK_MOD3_MASK }, + { "Mod4", GDK_MOD4_MASK }, + { "Mod5", GDK_MOD5_MASK }, + { 0, 0 } +}; + +void +OptionEditor::setup_keyboard_options () +{ + vector dumb; + Label* label; + + keyboard_mouse_table.set_border_width (12); + keyboard_mouse_table.set_row_spacings (5); + keyboard_mouse_table.set_col_spacings (5); + + /* internationalize and prepare for use with combos */ + + for (int i = 0; modifiers[i].name; ++i) { + dumb.push_back (_(modifiers[i].name)); + } + + edit_modifier_combo.set_popdown_strings (dumb); + edit_modifier_combo.get_entry()->set_editable (false); + edit_modifier_combo.get_entry()->set_name ("OptionsEntry"); + edit_modifier_combo.set_use_arrows_always (true); + edit_modifier_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::edit_modifier_chosen)); + + for (int x = 0; modifiers[x].name; ++x) { + if (modifiers[x].modifier == Keyboard::edit_modifier ()) { + edit_modifier_combo.get_entry()->set_text (_(modifiers[x].name)); + break; + } + } + + label = manage (new Label (_("Edit using"))); + label->set_name ("OptionsLabel"); + label->set_alignment (1.0, 0.5); + + keyboard_mouse_table.attach (*label, 0, 1, 0, 1, GTK_FILL|GTK_EXPAND, 0); + keyboard_mouse_table.attach (edit_modifier_combo, 1, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0); + + label = manage (new Label (_("+ button"))); + label->set_name ("OptionsLabel"); + + keyboard_mouse_table.attach (*label, 3, 4, 0, 1, GTK_FILL|GTK_EXPAND, 0); + keyboard_mouse_table.attach (edit_button_spin, 4, 5, 0, 1, GTK_FILL|GTK_EXPAND, 0); + + edit_button_spin.set_name ("OptionsEntry"); + edit_button_adjustment.set_value (Keyboard::edit_button()); + edit_button_adjustment.value_changed.connect (slot (*this, &OptionEditor::edit_button_changed)); + + delete_modifier_combo.set_popdown_strings (dumb); + delete_modifier_combo.get_entry()->set_editable (false); + delete_modifier_combo.get_entry()->set_name ("OptionsEntry"); + delete_modifier_combo.set_use_arrows_always (true); + delete_modifier_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::delete_modifier_chosen)); + + for (int x = 0; modifiers[x].name; ++x) { + if (modifiers[x].modifier == Keyboard::delete_modifier ()) { + delete_modifier_combo.get_entry()->set_text (_(modifiers[x].name)); + break; + } + } + + label = manage (new Label (_("Delete using"))); + label->set_name ("OptionsLabel"); + label->set_alignment (1.0, 0.5); + + keyboard_mouse_table.attach (*label, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND, 0); + keyboard_mouse_table.attach (delete_modifier_combo, 1, 2, 1, 2, GTK_FILL|GTK_EXPAND, 0); + + label = manage (new Label (_("+ button"))); + label->set_name ("OptionsLabel"); + + keyboard_mouse_table.attach (*label, 3, 4, 1, 2, GTK_FILL|GTK_EXPAND, 0); + keyboard_mouse_table.attach (delete_button_spin, 4, 5, 1, 2, GTK_FILL|GTK_EXPAND, 0); + + delete_button_spin.set_name ("OptionsEntry"); + delete_button_adjustment.set_value (Keyboard::delete_button()); + delete_button_adjustment.value_changed.connect (slot (*this, &OptionEditor::delete_button_changed)); + + snap_modifier_combo.set_popdown_strings (dumb); + snap_modifier_combo.get_entry()->set_editable (false); + snap_modifier_combo.get_entry()->set_name ("OptionsEntry"); + snap_modifier_combo.set_use_arrows_always (true); + snap_modifier_combo.get_popwin()->unmap_event.connect (slot (*this, &OptionEditor::snap_modifier_chosen)); + + for (int x = 0; modifiers[x].name; ++x) { + if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) { + snap_modifier_combo.get_entry()->set_text (_(modifiers[x].name)); + break; + } + } + + label = manage (new Label (_("Ignore snap using"))); + label->set_name ("OptionsLabel"); + label->set_alignment (1.0, 0.5); + + keyboard_mouse_table.attach (*label, 0, 1, 2, 3, GTK_FILL|GTK_EXPAND, 0); + keyboard_mouse_table.attach (snap_modifier_combo, 1, 2, 2, 3, GTK_FILL|GTK_EXPAND, 0); +} + +gint +OptionEditor::edit_modifier_chosen (GdkEventAny *ev) +{ + string txt; + + txt = edit_modifier_combo.get_entry()->get_text(); + + for (int i = 0; modifiers[i].name; ++i) { + if (txt == _(modifiers[i].name)) { + Keyboard::set_edit_modifier (modifiers[i].modifier); + break; + } + } + return TRUE; +} + +gint +OptionEditor::delete_modifier_chosen (GdkEventAny *ev) +{ + string txt; + + txt = delete_modifier_combo.get_entry()->get_text(); + + for (int i = 0; modifiers[i].name; ++i) { + if (txt == _(modifiers[i].name)) { + Keyboard::set_delete_modifier (modifiers[i].modifier); + break; + } + } + return TRUE; +} + +gint +OptionEditor::snap_modifier_chosen (GdkEventAny *ev) +{ + string txt; + + txt = snap_modifier_combo.get_entry()->get_text(); + + for (int i = 0; modifiers[i].name; ++i) { + if (txt == _(modifiers[i].name)) { + Keyboard::set_snap_modifier (modifiers[i].modifier); + break; + } + } + return TRUE; +} + +void +OptionEditor::delete_button_changed () +{ + Keyboard::set_delete_button ((guint) delete_button_adjustment.get_value()); +} + +void +OptionEditor::edit_button_changed () +{ + Keyboard::set_edit_button ((guint) edit_button_adjustment.get_value()); +} + +void +OptionEditor::fixup_combo_size (Gtk::Combo& combo, vector& strings) +{ + /* find the widest string */ + + string::size_type maxlen = 0; + string maxstring; + + for (vector::iterator i = strings.begin(); i != strings.end(); ++i) { + string::size_type l; + + if ((l = (*i).length()) > maxlen) { + maxlen = l; + maxstring = *i; + } + } + + /* try to include ascenders and descenders */ + + if (maxstring.length() > 2) { + maxstring[0] = 'g'; + maxstring[1] = 'l'; + } + + const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button + + set_usize_to_display_given_text (*combo.get_entry(), maxstring.c_str(), 10 + FUDGE, 10); +} + +void +OptionEditor::map_some_session_state (CheckButton& button, bool (Session::*get)() const) +{ + if (session) { + button.set_active ((session->*get)()); + } +} + diff --git a/gtk2_ardour/option_editor.h b/gtk2_ardour/option_editor.h new file mode 100644 index 0000000000..e4ed7de1b2 --- /dev/null +++ b/gtk2_ardour/option_editor.h @@ -0,0 +1,282 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __gtk_ardour_option_editor_h__ +#define __gtk_ardour_option_editor_h__ + +#include + +#include + +#include "ardour_dialog.h" +#include "editing.h" +#include "audio_clock.h" + +class ARDOUR_UI; +class PublicEditor; +class Mixer_UI; +class IOSelector; +class GainMeter; +class PannerUI; + +class OptionEditor : public ArdourDialog +{ + public: + OptionEditor (ARDOUR_UI&, PublicEditor&, Mixer_UI&); + ~OptionEditor (); + + void set_session (ARDOUR::Session *); + void save (); + + private: + ARDOUR::Session *session; + ARDOUR_UI& ui; + PublicEditor& editor; + Mixer_UI& mixer; + + Gtk::Notebook notebook; + + /* Generic */ + + void session_control_changed (ARDOUR::Session::ControlType); + void queue_session_control_changed (ARDOUR::Session::ControlType); + void map_some_session_state (Gtk::CheckButton& button, bool (ARDOUR::Session::*get)() const); + gint wm_close (GdkEventAny *); + void just_close_win(); + gint focus_out_event_handler (GdkEventFocus*, void (OptionEditor::*pmf)()); + + /* paths */ + + Gtk::Table path_table; + + Gtk::Entry session_raid_entry; + + Gtk::Combo native_format_combo; + + void setup_path_options(); + void add_session_paths (); + void remove_session_paths (); + gint native_format_chosen (GdkEventAny *); + void raid_path_changed (); + + /* fades */ + + // Gtk::Table fade_table; + + Gtk::VBox fade_packer; + Gtk::CheckButton auto_xfade_button; + Gtk::CheckButton xfade_active_button; + Gtk::Label layer_mode_label; + Gtk::Combo layer_mode_combo; + Gtk::Label xfade_model_label; + Gtk::Combo xfade_model_combo; + Gtk::Adjustment short_xfade_adjustment; + Gtk::HScale short_xfade_slider; + + void auto_xfade_clicked (); + void xfade_active_clicked (); + gint layer_mode_chosen (GdkEventAny*); + gint xfade_model_chosen (GdkEventAny*); + void setup_fade_options(); + void short_xfade_adjustment_changed (); + + /* solo */ + + Gtk::VBox solo_packer; + Gtk::CheckButton solo_latched_button; + Gtk::CheckButton solo_via_bus_button; + + void solo_latched_clicked(); + void solo_via_bus_clicked (); + + void setup_solo_options(); + + /* display */ + + Gtk::VBox display_packer; + Gtk::CheckButton show_waveforms_button; + Gtk::CheckButton show_waveforms_recording_button; + Gtk::CheckButton mixer_strip_width_button; + Gtk::CheckButton show_measures_button; + Gtk::CheckButton follow_playhead_button; + Gtk::Combo meter_hold_combo; + Gtk::Combo meter_falloff_combo; + + void setup_display_options(); + void show_waveforms_clicked (); + void show_waveforms_recording_clicked (); + void show_measures_clicked (); + void strip_width_clicked (); + void follow_playhead_clicked (); + gint meter_hold_chosen (GdkEventAny *); + gint meter_falloff_chosen (GdkEventAny *); + + void display_control_changed (Editing::DisplayControl); + + /* Sync */ + + Gtk::VBox sync_packer; + + Gtk::CheckButton send_mtc_button; + Gtk::CheckButton send_mmc_button; + Gtk::CheckButton jack_time_master_button; + Gtk::Combo slave_type_combo; + Gtk::Combo smpte_fps_combo; + AudioClock smpte_offset_clock; + Gtk::CheckButton smpte_offset_negative_button; + + void setup_sync_options (); + gint send_mtc_toggled (GdkEventButton*, Gtk::CheckButton*); + + gint slave_type_chosen (GdkEventAny*); + void jack_time_master_clicked (); + void jack_transport_master_clicked (); + gint smpte_fps_chosen (GdkEventAny*); + void smpte_offset_chosen (); + void smpte_offset_negative_clicked (); + + /* MIDI */ + + Gtk::VBox midi_packer; + Gtk::CheckButton midi_feedback_button; + Gtk::CheckButton midi_control_button; + Gtk::CheckButton mmc_control_button; + + void send_mmc_toggled (Gtk::CheckButton*); + void mmc_control_toggled (Gtk::CheckButton*); + void midi_control_toggled (Gtk::CheckButton*); + void midi_feedback_toggled (Gtk::CheckButton*); + + gint port_online_toggled (GdkEventButton*,MIDI::Port*,Gtk::ToggleButton*); + gint port_trace_in_toggled (GdkEventButton*,MIDI::Port*,Gtk::ToggleButton*); + gint port_trace_out_toggled (GdkEventButton*,MIDI::Port*,Gtk::ToggleButton*); + + gint mmc_port_chosen (GdkEventButton*,MIDI::Port*,Gtk::RadioButton*); + gint mtc_port_chosen (GdkEventButton*,MIDI::Port*,Gtk::RadioButton*); + gint midi_port_chosen (GdkEventButton*,MIDI::Port*,Gtk::RadioButton*); + + void map_port_online (MIDI::Port*, Gtk::ToggleButton*); + + void setup_midi_options(); + + enum PortIndex { + MtcIndex = 0, + MmcIndex = 1, + MidiIndex = 2 + }; + + std::map > port_toggle_buttons; + + /* Click */ + + IOSelector* click_io_selector; + GainMeter* click_gpm; + PannerUI* click_panner; + Gtk::VBox click_packer; + Gtk::Table click_table; + Gtk::Entry click_path_entry; + Gtk::Entry click_emphasis_path_entry; + Gtk::Button click_browse_button; + Gtk::Button click_emphasis_browse_button; + + void setup_click_editor (); + void clear_click_editor (); + + void click_chosen (vector paths, bool ignore); + void click_emphasis_chosen (vector paths, bool ignore); + + void click_browse_clicked (); + void click_emphasis_browse_clicked (); + + void click_sound_changed (); + void click_emphasis_sound_changed (); + + /* Auditioner */ + + Gtk::VBox audition_packer; + Gtk::HBox audition_hpacker; + Gtk::Label audition_label; + IOSelector* auditioner_io_selector; + GainMeter* auditioner_gpm; + PannerUI* auditioner_panner; + + void setup_auditioner_editor (); + void clear_auditioner_editor (); + void connect_audition_editor (); + + /* keyboard/mouse */ + + Gtk::Table keyboard_mouse_table; + Gtk::Combo edit_modifier_combo; + Gtk::Combo delete_modifier_combo; + Gtk::Combo snap_modifier_combo; + Gtk::Adjustment delete_button_adjustment; + Gtk::SpinButton delete_button_spin; + Gtk::Adjustment edit_button_adjustment; + Gtk::SpinButton edit_button_spin; + + void setup_keyboard_options (); + gint delete_modifier_chosen (GdkEventAny*); + gint edit_modifier_chosen (GdkEventAny*); + gint snap_modifier_chosen (GdkEventAny*); + void edit_button_changed (); + void delete_button_changed (); + + /* Miscellany */ + + Gtk::VBox misc_packer; + + Gtk::CheckButton auto_connect_inputs_button; + + Gtk::RadioButton auto_connect_output_physical_button; + Gtk::RadioButton auto_connect_output_master_button; + Gtk::RadioButton auto_connect_output_manual_button; + + Gtk::CheckButton hw_monitor_button; + Gtk::CheckButton sw_monitor_button; + Gtk::CheckButton plugins_stop_button; + Gtk::CheckButton plugins_on_rec_button; + Gtk::CheckButton verify_remove_last_capture_button; + Gtk::CheckButton stop_rec_on_xrun_button; + Gtk::CheckButton stop_at_end_button; + Gtk::CheckButton debug_keyboard_button; + Gtk::CheckButton speed_quieten_button; + + void setup_misc_options (); + void plugins_stop_with_transport_clicked (); + void verify_remove_last_capture_clicked (); + void plugins_on_while_recording_clicked (); + void auto_connect_inputs_clicked (); + void auto_connect_output_physical_clicked (); + void auto_connect_output_master_clicked (); + void auto_connect_output_manual_clicked (); + void hw_monitor_clicked (); + void sw_monitor_clicked (); + void stop_rec_on_xrun_clicked (); + void stop_at_end_clicked (); + void debug_keyboard_clicked (); + void speed_quieten_clicked (); + + void fixup_combo_size (Gtk::Combo&, vector& strings); +}; + +#endif /* __gtk_ardour_option_editor_h__ */ + + diff --git a/gtk2_ardour/opts.cc b/gtk2_ardour/opts.cc new file mode 100644 index 0000000000..48245651e8 --- /dev/null +++ b/gtk2_ardour/opts.cc @@ -0,0 +1,154 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include "opts.h" + +#include "i18n.h" + +using namespace std; + +string GTK_ARDOUR::session_name = ""; +string GTK_ARDOUR::jack_client_name = "ardour"; +bool GTK_ARDOUR::show_key_actions = false; +bool GTK_ARDOUR::no_splash = true; +bool GTK_ARDOUR::just_version = false; +bool GTK_ARDOUR::use_vst = true; +bool GTK_ARDOUR::new_session = false; +char* GTK_ARDOUR::curvetest_file = 0; +bool GTK_ARDOUR::try_hw_optimization = false; + +using namespace GTK_ARDOUR; + +int +print_help (const char *execname) +{ + cout << _("Usage: ") << execname << "\n" + << _(" -v, --version Show version information\n") + << _(" -h, --help Print this message\n") + << _(" -b, --bindings Print all possible keyboard binding names\n") + << _(" -n, --show-splash Show splash screen\n") + << _(" -c, --name name Use a specific jack client name, default is ardour\n") + << _(" -N, --new session-name Create a new session from the command line\n") + << _(" -o, --use-hw-optimizations Try to use h/w specific optimizations\n") +#ifdef VST_SUPPORT + << _(" -V, --novst Do not use VST support\n") +#endif + << _(" [session-name] Name of session to load\n") + << _(" -C, --curvetest filename Curve algorithm debugger\n") + ; + return 1; + +} + +int +GTK_ARDOUR::parse_opts (int argc, char *argv[]) + +{ + const char *optstring = "U:hbvVnoc:C:N:"; + const char *execname = strrchr (argv[0], '/'); + + if (execname == 0) { + execname = argv[0]; + } else { + execname++; + } + + const struct option longopts[] = { + { "version", 0, 0, 'v' }, + { "help", 0, 0, 'h' }, + { "bindings", 0, 0, 'b' }, + { "show-splash", 0, 0, 'n' }, + { "name", 1, 0, 'c' }, + { "novst", 0, 0, 'V' }, + { "new", 1, 0, 'N' }, + { "use-hw-optimizations", 0, 0, 'o' }, + { "curvetest", 1, 0, 'C' }, + { 0, 0, 0, 0 } + }; + + int option_index = 0; + int c = 0; + + while (1) { + c = getopt_long (argc, argv, optstring, longopts, &option_index); + + if (c == -1) { + break; + } + + switch (c) { + case 0: + break; + + case 'v': + just_version = true; + break; + + case 'h': + print_help (execname); + exit (0); + break; + case 'b': + show_key_actions = true; + break; + + case 'n': + no_splash = false; + break; + + case 'N': + new_session = true; + session_name = optarg; + break; + + case 'o': + try_hw_optimization = true; + break; + + case 'V': +#ifdef VST_SUPPORT + use_vst = false; +#endif /* VST_SUPPORT */ + break; + + case 'c': + jack_client_name = optarg; + break; + + case 'C': + curvetest_file = optarg; + break; + + default: + break; + } + } + + if (optind < argc) { + session_name = argv[optind++]; + } + + return 0; +} + diff --git a/gtk2_ardour/opts.h b/gtk2_ardour/opts.h new file mode 100644 index 0000000000..c07dcc3664 --- /dev/null +++ b/gtk2_ardour/opts.h @@ -0,0 +1,44 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_opts_h__ +#define __ardour_opts_h__ + +#include + +using std::string; + +namespace GTK_ARDOUR { + +extern string session_name; +extern bool show_key_actions; +extern bool no_splash; +extern bool just_version; +extern string jack_client_name; +extern bool use_vst; +extern bool new_session; +extern char* curvetest_file; +extern bool try_hw_optimization; + +extern int32_t parse_opts (int argc, char *argv[]); + +} + +#endif /* __ardour_opts_h__ */ diff --git a/gtk2_ardour/pan_automation_time_axis.cc b/gtk2_ardour/pan_automation_time_axis.cc new file mode 100644 index 0000000000..f691307e9c --- /dev/null +++ b/gtk2_ardour/pan_automation_time_axis.cc @@ -0,0 +1,92 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include + +#include "pan_automation_time_axis.h" +#include "automation_line.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; + +PanAutomationTimeAxisView::PanAutomationTimeAxisView (Session& s, Route& r, PublicEditor& e, TimeAxisView& parent, Widget* p, std::string n) + + : AxisView (s), + AutomationTimeAxisView (s, r, e, parent, p, n, X_("pan"), "") +{ +} + +PanAutomationTimeAxisView::~PanAutomationTimeAxisView () +{ +} + +void +PanAutomationTimeAxisView::add_automation_event (GtkCanvasItem* item, GdkEvent* event, jack_nframes_t when, double y) +{ + if (lines.empty()) { + /* no data, possibly caused by no outputs/inputs */ + return; + } + + if (lines.size() > 1) { + + Gtkmmext::PopUp* msg = new Gtkmmext::PopUp (GTK_WIN_POS_MOUSE, 5000, true); + + msg->set_text (_("You can't graphically edit panning of more than stream")); + msg->touch (); + + return; + } + + double x = 0; + + gtk_canvas_item_w2i (canvas_display, &x, &y); + + /* compute vertical fractional position */ + + y = 1.0 - (y / height); + + /* map using line */ + + lines.front()->view_to_model_y (y); + + AutomationList& alist (lines.front()->the_list()); + + _session.begin_reversible_command (_("add pan automation event")); + _session.add_undo (alist.get_memento()); + alist.add (when, y); + _session.add_undo (alist.get_memento()); + _session.commit_reversible_command (); + _session.set_dirty (); +} + +void +PanAutomationTimeAxisView::set_automation_state (AutoState state) +{ + if (!ignore_state_request) { + route.panner().set_automation_state (state); + } +} diff --git a/gtk2_ardour/pan_automation_time_axis.h b/gtk2_ardour/pan_automation_time_axis.h new file mode 100644 index 0000000000..16b0808148 --- /dev/null +++ b/gtk2_ardour/pan_automation_time_axis.h @@ -0,0 +1,29 @@ +#ifndef __ardour_gtk_pan_automation_time_axis_h__ +#define __ardour_gtk_pan_automation_time_axis_h__ + +#include "automation_time_axis.h" + +namespace ARDOUR { + class Redirect; +} + +class PanAutomationTimeAxisView : public AutomationTimeAxisView +{ + public: + PanAutomationTimeAxisView (ARDOUR::Session&, + ARDOUR::Route&, + PublicEditor&, + TimeAxisView& parent_axis, + Gtk::Widget* parent, + std::string name); + + ~PanAutomationTimeAxisView(); + + void add_automation_event (GtkCanvasItem *item, GdkEvent *event, jack_nframes_t, double); + + private: + void automation_changed (); + void set_automation_state (ARDOUR::AutoState); +}; + +#endif /* __ardour_gtk_pan_automation_time_axis_h__ */ diff --git a/gtk2_ardour/panner2d.cc b/gtk2_ardour/panner2d.cc new file mode 100644 index 0000000000..ceec33868b --- /dev/null +++ b/gtk2_ardour/panner2d.cc @@ -0,0 +1,636 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include +#include +#include + +#include "panner2d.h" +#include "keyboard.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace std; +using namespace Gtk; +using namespace SigC; +using namespace ARDOUR; + +Panner2d::Target::Target (float xa, float ya, const char *txt) + : x (xa), y (ya), text (txt ? strdup (txt) : 0) +{ + if (text) { + textlen = strlen (txt); + } else { + textlen = 0; + } +} + +Panner2d::Target::~Target () +{ + if (text) { + free (text); + } +} + +Panner2d::Panner2d (Panner& p, int32_t w, int32_t h) + : panner (p), width (w), height (h) +{ + context_menu = 0; + bypass_menu_item = 0; + + allow_x = false; + allow_y = false; + allow_target = false; + + panner.StateChanged.connect (slot (*this, &Panner2d::handle_state_change)); + + drag_target = 0; + set_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_POINTER_MOTION_MASK); + +} + +Panner2d::~Panner2d() +{ + for (Targets::iterator i = targets.begin(); i != targets.end(); ++i) { + delete i->second; + } +} + +void +Panner2d::reset (uint32_t n_inputs) +{ + /* add pucks */ + + drop_pucks (); + + switch (n_inputs) { + case 0: + break; + + case 1: + add_puck ("", 0.0f, 0.5f); + break; + + case 2: + add_puck ("L", 0.5f, 0.25f); + add_puck ("R", 0.25f, 0.5f); + show_puck (0); + show_puck (1); + break; + + default: + for (uint32_t i = 0; i < n_inputs; ++i) { + char buf[64]; + snprintf (buf, sizeof (buf), "%" PRIu32, i); + add_puck (buf, 0.0f, 0.5f); + show_puck (i); + } + break; + } + + /* add all outputs */ + + drop_targets (); + + for (uint32_t n = 0; n < panner.nouts(); ++n) { + add_target (panner.output (n).x, panner.output (n).y); + } + + allow_x_motion (true); + allow_y_motion (true); + allow_target_motion (true); +} + +void +Panner2d::size_allocate_impl (GtkAllocation *alloc) +{ + width = alloc->width; + height = alloc->height; + + DrawingArea::size_allocate_impl (alloc); +} + +int +Panner2d::add_puck (const char* text, float x, float y) +{ + Target* puck = new Target (x, y, text); + + pair newpair; + newpair.first = pucks.size(); + newpair.second = puck; + + pucks.insert (newpair); + puck->visible = true; + + return 0; +} + +int +Panner2d::add_target (float x, float y) +{ + Target *target = new Target (x, y, ""); + + pair newpair; + newpair.first = targets.size(); + newpair.second = target; + + targets.insert (newpair); + target->visible = true; + queue_draw (); + + return newpair.first; +} + +void +Panner2d::drop_targets () +{ + for (Targets::iterator i = targets.begin(); i != targets.end(); ) { + + Targets::iterator tmp; + + tmp = i; + ++tmp; + + delete i->second; + targets.erase (i); + + i = tmp; + } + + queue_draw (); +} + +void +Panner2d::drop_pucks () +{ + for (Targets::iterator i = pucks.begin(); i != pucks.end(); ) { + + Targets::iterator tmp; + + tmp = i; + ++tmp; + + delete i->second; + pucks.erase (i); + + i = tmp; + } + + queue_draw (); +} + +void +Panner2d::remove_target (int which) +{ + Targets::iterator i = targets.find (which); + + if (i != targets.end()) { + delete i->second; + targets.erase (i); + queue_draw (); + } +} + +void +Panner2d::handle_state_change () +{ + ENSURE_GUI_THREAD(slot (*this, &Panner2d::handle_state_change)); + + queue_draw (); +} + +void +Panner2d::move_target (int which, float x, float y) +{ + Targets::iterator i = targets.find (which); + Target *target; + + if (!allow_target) { + return; + } + + if (i != targets.end()) { + target = i->second; + target->x = x; + target->y = y; + + queue_draw (); + } +} + +void +Panner2d::move_puck (int which, float x, float y) +{ + Targets::iterator i = pucks.find (which); + Target *target; + + if (i != pucks.end()) { + target = i->second; + target->x = x; + target->y = y; + + queue_draw (); + } +} + +void +Panner2d::show_puck (int which) +{ + Targets::iterator i = pucks.find (which); + + if (i != pucks.end()) { + Target* puck = i->second; + if (!puck->visible) { + puck->visible = true; + queue_draw (); + } + } +} + +void +Panner2d::hide_puck (int which) +{ + Targets::iterator i = pucks.find (which); + + if (i != pucks.end()) { + Target* puck = i->second; + if (!puck->visible) { + puck->visible = false; + queue_draw (); + } + } +} + +void +Panner2d::show_target (int which) +{ + Targets::iterator i = targets.find (which); + if (i != targets.end()) { + if (!i->second->visible) { + i->second->visible = true; + queue_draw (); + } + } +} + +void +Panner2d::hide_target (int which) +{ + Targets::iterator i = targets.find (which); + if (i != targets.end()) { + if (i->second->visible) { + i->second->visible = false; + queue_draw (); + } + } +} + +Panner2d::Target * +Panner2d::find_closest_object (gdouble x, gdouble y, int& which, bool& is_puck) const +{ + gdouble efx, efy; + Target *closest = 0; + Target *candidate; + float distance; + float best_distance = FLT_MAX; + int pwhich; + + efx = x/width; + efy = y/height; + which = 0; + pwhich = 0; + is_puck = false; + + for (Targets::const_iterator i = targets.begin(); i != targets.end(); ++i, ++which) { + candidate = i->second; + + distance = sqrt ((candidate->x - efx) * (candidate->x - efx) + + (candidate->y - efy) * (candidate->y - efy)); + + if (distance < best_distance) { + closest = candidate; + best_distance = distance; + } + } + + for (Targets::const_iterator i = pucks.begin(); i != pucks.end(); ++i, ++pwhich) { + candidate = i->second; + + distance = sqrt ((candidate->x - efx) * (candidate->x - efx) + + (candidate->y - efy) * (candidate->y - efy)); + + if (distance < best_distance) { + closest = candidate; + best_distance = distance; + is_puck = true; + which = pwhich; + } + } + + return closest; +} + +gint +Panner2d::motion_notify_event_impl (GdkEventMotion *ev) +{ + gint x, y; + GdkModifierType state; + + if (ev->is_hint) { + gdk_window_get_pointer (ev->window, &x, &y, &state); + } else { + x = (int) floor (ev->x); + y = (int) floor (ev->y); + state = (GdkModifierType) ev->state; + } + return handle_motion (x, y, state); +} +gint +Panner2d::handle_motion (gint evx, gint evy, GdkModifierType state) +{ + if (drag_target == 0 || (state & GDK_BUTTON1_MASK) == 0) { + return FALSE; + } + + int x, y; + bool need_move = false; + + if (!drag_is_puck && !allow_target) { + return TRUE; + } + + if (allow_x || !drag_is_puck) { + float new_x; + x = min (evx, width - 1); + x = max (x, 0); + new_x = (float) x / (width - 1); + if (new_x != drag_target->x) { + drag_target->x = new_x; + need_move = true; + } + } + + if (allow_y || drag_is_puck) { + float new_y; + y = min (evy, height - 1); + y = max (y, 0); + new_y = (float) y / (height - 1); + if (new_y != drag_target->y) { + drag_target->y = new_y; + need_move = true; + } + } + + if (need_move) { + queue_draw (); + + if (drag_is_puck) { + + panner[drag_index]->set_position (drag_target->x, drag_target->y); + + } else { + + TargetMoved (drag_index); + } + } + + return TRUE; +} + +gint +Panner2d::expose_event_impl (GdkEventExpose *event) +{ + gint x, y; + float fx, fy; + + /* redraw the background */ + + get_window().draw_rectangle (get_style()->get_bg_gc(get_state()), + true, + event->area.x, event->area.y, + event->area.width, event->area.height); + + + if (!panner.bypassed()) { + + for (Targets::iterator i = pucks.begin(); i != pucks.end(); ++i) { + + Target* puck = i->second; + + if (puck->visible) { + /* redraw puck */ + + fx = min (puck->x, 1.0f); + fx = max (fx, -1.0f); + x = (gint) floor (width * fx - 4); + + fy = min (puck->y, 1.0f); + fy = max (fy, -1.0f); + y = (gint) floor (height * fy - 4); + + get_window().draw_arc (get_style()->get_fg_gc(GTK_STATE_NORMAL), + true, + x, y, + 8, 8, + 0, 360 * 64); + get_window().draw_text (get_style()->get_font(), + get_style()->get_fg_gc(GTK_STATE_NORMAL), + x + 6, y + 6, + puck->text, + puck->textlen); + } + } + + /* redraw any visible targets */ + + for (Targets::iterator i = targets.begin(); i != targets.end(); ++i) { + Target *target = i->second; + + if (target->visible) { + + /* why -8 ??? why is this necessary ? */ + + fx = min (target->x, 1.0f); + fx = max (fx, -1.0f); + x = (gint) floor ((width - 8) * fx); + + fy = min (target->y, 1.0f); + fy = max (fy, -1.0f); + y = (gint) floor ((height - 8) * fy); + + get_window().draw_rectangle (get_style()->get_fg_gc(GTK_STATE_ACTIVE), + true, + x, y, + 4, 4); + } + } + } + + return TRUE; +} + +gint +Panner2d::button_press_event_impl (GdkEventButton *ev) +{ + switch (ev->button) { + case 1: + gint x, y; + GdkModifierType state; + + drag_target = find_closest_object (ev->x, ev->y, drag_index, drag_is_puck); + + x = (int) floor (ev->x); + y = (int) floor (ev->y); + state = (GdkModifierType) ev->state; + + return handle_motion (x, y, state); + break; + default: + break; + } + + return FALSE; +} + +gint +Panner2d::button_release_event_impl (GdkEventButton *ev) +{ + switch (ev->button) { + case 1: + gint x, y; + int ret; + GdkModifierType state; + + x = (int) floor (ev->x); + y = (int) floor (ev->y); + state = (GdkModifierType) ev->state; + + if (drag_is_puck && (Keyboard::modifier_state_contains (state, Keyboard::Shift))) { + + for (Targets::iterator i = pucks.begin(); i != pucks.end(); ++i) { + Target* puck = i->second; + puck->x = 0.5; + puck->y = 0.5; + } + + queue_draw (); + PuckMoved (-1); + ret = TRUE; + + } else { + ret = handle_motion (x, y, state); + } + + drag_target = 0; + + return ret; + break; + case 2: + toggle_bypass (); + return TRUE; + + case 3: + show_context_menu (); + break; + + } + + return FALSE; +} + +void +Panner2d::toggle_bypass () +{ + if (bypass_menu_item && (panner.bypassed() != bypass_menu_item->get_active())) { + panner.set_bypassed (!panner.bypassed()); + } +} + +void +Panner2d::show_context_menu () +{ + using namespace Menu_Helpers; + + if (context_menu == 0) { + context_menu = manage (new Menu); + context_menu->set_name ("ArdourContextMenu"); + MenuList& items = context_menu->items(); + + items.push_back (CheckMenuElem (_("Bypass"))); + bypass_menu_item = static_cast (items.back()); + bypass_menu_item->toggled.connect (slot (*this, &Panner2d::toggle_bypass)); + + } + + bypass_menu_item->set_active (panner.bypassed()); + context_menu->popup (1, 0); +} + +void +Panner2d::allow_x_motion (bool yn) +{ + allow_x = yn; +} + +void +Panner2d::allow_target_motion (bool yn) +{ + allow_target = yn; +} + +void +Panner2d::allow_y_motion (bool yn) +{ + allow_y = yn; +} + +int +Panner2d::puck_position (int which, float& x, float& y) +{ + Targets::iterator i; + + if ((i = pucks.find (which)) != pucks.end()) { + x = i->second->x; + y = i->second->y; + return 0; + } + + return -1; +} + +int +Panner2d::target_position (int which, float& x, float& y) +{ + Targets::iterator i; + + if ((i = targets.find (which)) != targets.end()) { + x = i->second->x; + y = i->second->y; + return 0; + } + + return -1; +} + diff --git a/gtk2_ardour/panner2d.h b/gtk2_ardour/panner2d.h new file mode 100644 index 0000000000..8161be29f2 --- /dev/null +++ b/gtk2_ardour/panner2d.h @@ -0,0 +1,115 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_panner_2d_h__ +#define __ardour_panner_2d_h__ + +#include +#include +#include +#include + +using std::map; +using std::string; + +namespace ARDOUR { + class Panner; +} + +class Panner2d : public Gtk::DrawingArea +{ + public: + Panner2d (ARDOUR::Panner&, int32_t width, int32_t height); + ~Panner2d (); + + int puck_position (int which_puck, float& x, float& y); + int target_position (int which_target, float& x, float& y); + + void allow_x_motion(bool); + void allow_y_motion(bool); + void allow_target_motion (bool); + + void hide_puck (int which); + void show_puck (int which); + int add_target (float x, float y); + int add_puck (const char* text, float x, float y); + void hide_target (int); + void show_target (int); + void remove_target (int); + void drop_targets (); + void drop_pucks (); + void move_target (int, float x, float y); + void move_puck (int, float x, float y); + void reset (uint32_t n_inputs); + + SigC::Signal1 PuckMoved; + SigC::Signal1 TargetMoved; + + protected: + gint expose_event_impl (GdkEventExpose *); + gint button_press_event_impl (GdkEventButton *); + gint button_release_event_impl (GdkEventButton *); + gint motion_notify_event_impl (GdkEventMotion *); + void size_allocate_impl (GtkAllocation* alloc); + + private: + struct Target { + float x; + float y; + bool visible; + char* text; + size_t textlen; + + Target (float xa, float ya, const char* txt = 0); + ~Target (); + }; + + ARDOUR::Panner& panner; + Gtk::Menu* context_menu; + Gtk::CheckMenuItem* bypass_menu_item; + + typedef map Targets; + Targets targets; + Targets pucks; + + Target *drag_target; + int drag_index; + bool drag_is_puck; + bool allow_x; + bool allow_y; + bool allow_target; + int width; + int height; + + bool bypassflag; + + gint compute_x (float); + gint compute_y (float); + + Target *find_closest_object (gdouble x, gdouble y, int& which, bool& is_puck) const; + + gint handle_motion (gint, gint, GdkModifierType); + + void toggle_bypass (); + void show_context_menu (); + void handle_state_change (); +}; + +#endif /* __ardour_panner_2d_h__ */ diff --git a/gtk2_ardour/panner_ui.cc b/gtk2_ardour/panner_ui.cc new file mode 100644 index 0000000000..42525466c6 --- /dev/null +++ b/gtk2_ardour/panner_ui.cc @@ -0,0 +1,658 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ardour_ui.h" +#include "panner_ui.h" +#include "panner2d.h" +#include "utils.h" +#include "gui_thread.h" + +#include +#include +#include + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtkmmext; +using namespace Gtk; +using namespace SigC; + +/* XPM */ +static const gchar * forwdblarrow_xpm[] = { +"20 11 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" .. ", +" .+. ", +" .++. ", +" ..............+++. ", +" .+++++++++++++++++.", +" ...................", +" .+++++++++++++++++.", +" ..............+++. ", +" .++. ", +" .+. ", +" .. "}; + +/* XPM */ +static const gchar * revdblarrow_xpm[] = { +"20 11 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" .. ", +" .+. ", +" .++. ", +" ..............+++. ", +" .+++++++++++++++++.", +" ...................", +" .+++++++++++++++++.", +" .+++..............", +" .++. ", +" .+. ", +" .. "}; + + +PannerUI::PannerUI (IO& io, Session& s) + : _io (io), + _session (s), + panning_up_arrow (GTK_ARROW_UP, GTK_SHADOW_OUT), + panning_down_arrow (GTK_ARROW_DOWN, GTK_SHADOW_OUT), + panning_link_button (_("link")) + +{ + ignore_toggle = false; + pan_menu = 0; + in_pan_update = false; + + pan_bar_packer.set_usize (-1, 61); + panning_viewport.set_usize (61, 61); + + panning_viewport.set_name (X_("BaseFrame")); + + ARDOUR_UI::instance()->tooltips().set_tip (panning_link_button, + _("panning link control")); + ARDOUR_UI::instance()->tooltips().set_tip (panning_link_direction_button, + _("panning link direction")); + + panning_link_box.pack_start (panning_link_button, true, true); + panning_link_box.pack_start (panning_link_direction_button, true, true); + + panning_link_button.set_name (X_("PanningLinkButton")); + panning_link_direction_button.set_name (X_("PanningLinkDirectionButton")); + + /* the pixmap will be reset at some point, but the key thing is that + we need a pixmap in the button just to get started. + */ + + panning_link_direction_button.add (*(manage (new Pixmap (forwdblarrow_xpm)))); + + panning_link_direction_button.clicked.connect + (slot (*this, &PannerUI::panning_link_direction_clicked)); + + panning_link_button.button_press_event.connect + (slot (*this, &PannerUI::panning_link_button_press)); + panning_link_button.button_release_event.connect + (slot (*this, &PannerUI::panning_link_button_release)); + + panning_up.set_border_width (3); + panning_down.set_border_width (3); + panning_up.add (panning_up_arrow); + panning_down.add (panning_down_arrow); + panning_up.set_name (X_("PanScrollerBase")); + panning_down.set_name (X_("PanScrollerBase")); + panning_up_arrow.set_name (X_("PanScrollerArrow")); + panning_down_arrow.set_name (X_("PanScrollerArrow")); + + pan_vbox.set_spacing (4); + pan_vbox.pack_start (panning_viewport, false, false); + pan_vbox.pack_start (panning_link_box, false, false); + + pack_start (pan_vbox, true, false); + pan_vbox.show_all (); + show (); + + panner = 0; + + _io.panner().Changed.connect (slot (*this, &PannerUI::panner_changed)); + _io.panner().LinkStateChanged.connect (slot (*this, &PannerUI::update_pan_linkage)); + _io.panner().StateChanged.connect (slot (*this, &PannerUI::update_pan_state)); + + pan_changed (0); + update_pan_sensitive (); + update_pan_linkage (); +} + +gint +PannerUI::panning_link_button_press (GdkEventButton* ev) +{ + return stop_signal (panning_link_button, "button-press-event"); +} + +gint +PannerUI::panning_link_button_release (GdkEventButton* ev) +{ + if (!ignore_toggle) { + _io.panner().set_linked (!_io.panner().linked()); + } + return TRUE; +} + +void +PannerUI::panning_link_direction_clicked() +{ + switch (_io.panner().link_direction()) { + case Panner::SameDirection: + _io.panner().set_link_direction (Panner::OppositeDirection); + break; + default: + _io.panner().set_link_direction (Panner::SameDirection); + break; + } +} + +void +PannerUI::update_pan_linkage () +{ + ENSURE_GUI_THREAD(slot (*this, &PannerUI::update_pan_linkage)); + + bool x = _io.panner().linked(); + bool bx = panning_link_button.get_active(); + + if (x != bx) { + + ignore_toggle = true; + panning_link_button.set_active (x); + ignore_toggle = false; + } + + panning_link_direction_button.set_sensitive (x); + + switch (_io.panner().link_direction()) { + case Panner::SameDirection: + static_cast (panning_link_direction_button.get_child())->set (forwdblarrow_xpm); + break; + default: + static_cast (panning_link_direction_button.get_child())->set (revdblarrow_xpm); + break; + } +} + +void +PannerUI::set_width (Width w) +{ + switch (w) { + case Wide: + panning_viewport.set_usize (61, 61); + if (panner) { + panner->set_usize (61, 61); + } + for (vector::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) { + (*i)->set_usize (61, 15); + } + static_cast (panning_link_button.get_child())->set_text (_("link")); + break; + case Narrow: + panning_viewport.set_usize (31, 61); + if (panner) { + panner->set_usize (31, 61); + } + for (vector::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) { + (*i)->set_usize (31, 15); + } + static_cast (panning_link_button.get_child())->set_text (_("L")); + break; + } + + _width = w; +} + + +PannerUI::~PannerUI () +{ + for (vector::iterator i = pan_adjustments.begin(); i != pan_adjustments.end(); ++i) { + delete (*i); + } + + for (vector::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) { + delete (*i); + } + + if (panner) { + delete panner; + } + + if (pan_menu) { + delete pan_menu; + } + +} + + +gint +PannerUI::entry_focus_event (GdkEventFocus* ev) +{ + if (ev->in) { + ARDOUR_UI::instance()->allow_focus (true); + } else { + ARDOUR_UI::instance()->allow_focus (false); + } + return TRUE; +} + +void +PannerUI::panner_changed () +{ + ENSURE_GUI_THREAD (slot (*this, &PannerUI::panner_changed)); + setup_pan (); +} + +void +PannerUI::update_pan_state () +{ + /* currently nothing to do */ + // ENSURE_GUI_THREAD (slot (*this, &PannerUI::update_panner_state)); +} + +void +PannerUI::setup_pan () +{ + uint32_t nouts = _io.n_outputs (); + + if (nouts == 0 || nouts == 1) { + + while (!pan_adjustments.empty()) { + delete pan_bars.back(); + pan_bars.pop_back (); + delete pan_adjustments.back(); + pan_adjustments.pop_back (); + } + + } else if (nouts == 2) { + + vector::size_type asz; + uint32_t npans = _io.panner().size(); + + while (!pan_adjustments.empty()) { + delete pan_bars.back(); + pan_bars.pop_back (); + delete pan_adjustments.back(); + pan_adjustments.pop_back (); + } + + while ((asz = pan_adjustments.size()) < npans) { + + float x; + BarController* bc; + + /* initialize adjustment with current value of panner */ + + _io.panner()[asz]->get_position (x); + + pan_adjustments.push_back (new Adjustment (x, 0, 1.0, 0.05, 0.1)); + pan_adjustments.back()->value_changed.connect (bind (slot (*this, &PannerUI::pan_adjustment_changed), (uint32_t) asz)); + + _io.panner()[asz]->Changed.connect (bind (slot (*this, &PannerUI::pan_value_changed), (uint32_t) asz)); + + bc = new BarController (*pan_adjustments[asz], + &_io.panner()[asz]->midi_control(), + bind (slot (*this, &PannerUI::pan_printer), pan_adjustments[asz])); + + if (_session.midi_port()) { + _io.panner()[asz]->reset_midi_control (_session.midi_port(), true); + } + + bc->set_name ("PanSlider"); + bc->set_shadow_type (GTK_SHADOW_NONE); + bc->set_style (BarController::Line); + bc->get_spin_button().focus_in_event.connect (slot (*this, &PannerUI::entry_focus_event)); + bc->get_spin_button().focus_out_event.connect (slot (*this, &PannerUI::entry_focus_event)); + + bc->StartGesture.connect (bind (slot (_io, &IO::start_pan_touch), (uint32_t) asz)); + bc->StopGesture.connect (bind (slot (_io, &IO::end_pan_touch), (uint32_t) asz)); + + char buf[64]; + snprintf (buf, sizeof (buf), _("panner for channel %u"), asz + 1); + ARDOUR_UI::instance()->tooltips().set_tip (bc->event_widget(), buf); + + bc->event_widget().button_release_event.connect + (bind (slot (*this, &PannerUI::pan_button_event), (uint32_t) asz)); + + pan_bars.push_back (bc); + switch (_width) { + case Wide: + pan_bars.back()->set_usize (61, 15); + break; + case Narrow: + pan_bars.back()->set_usize (31, 15); + break; + } + + pan_bar_packer.pack_start (*pan_bars.back(), false, false); + } + + /* now that we actually have the pan bars, + set their sensitivity based on current + automation state. + */ + + update_pan_sensitive (); + + panning_viewport.remove (); + panning_viewport.add (pan_bar_packer); + panning_viewport.show_all (); + + } else { + + int w = 0; + + switch (_width) { + case Wide: + w = 61; + break; + case Narrow: + w = 31; + break; + } + + if (panner == 0) { + panner = new Panner2d (_io.panner(), w, 61); + panner->set_name ("MixerPanZone"); + panner->show (); + } + + update_pan_sensitive (); + panner->reset (_io.n_inputs()); + panner->set_usize (w, 61); + + /* and finally, add it to the panner frame */ + + panning_viewport.remove (); + panning_viewport.add (*panner); + panning_viewport.show_all (); + } +} + +gint +PannerUI::pan_button_event (GdkEventButton* ev, uint32_t which) +{ + switch (ev->button) { + case 3: + if (pan_menu == 0) { + pan_menu = manage (new Menu); + pan_menu->set_name ("ArdourContextMenu"); + } + build_pan_menu (which); + pan_menu->popup (1, ev->time); + return TRUE; + break; + default: + return FALSE; + } + + return FALSE; // what's wrong with gcc? +} + +void +PannerUI::build_pan_menu (uint32_t which) +{ + using namespace Menu_Helpers; + MenuList& items (pan_menu->items()); + + items.clear (); + + items.push_back (CheckMenuElem (_("Mute"))); + + /* set state first, connect second */ + + (dynamic_cast (items.back()))->set_active (_io.panner()[which]->muted()); + (dynamic_cast (items.back()))->toggled.connect + (bind (slot (*this, &PannerUI::pan_mute), which)); + + items.push_back (CheckMenuElem (_("Bypass"), slot (*this, &PannerUI::pan_bypass_toggle))); + bypass_menu_item = static_cast (items.back()); + + /* set state first, connect second */ + + bypass_menu_item->set_active (_io.panner().bypassed()); + bypass_menu_item->toggled.connect (slot (*this, &PannerUI::pan_bypass_toggle)); + + items.push_back (MenuElem (_("Reset"), slot (*this, &PannerUI::pan_reset))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Reset all"))); +} + +void +PannerUI::pan_mute (uint32_t which) +{ + StreamPanner* sp = _io.panner()[which]; + sp->set_muted (!sp->muted()); +} + +void +PannerUI::pan_bypass_toggle () +{ + if (bypass_menu_item && (_io.panner().bypassed() != bypass_menu_item->get_active())) { + _io.panner().set_bypassed (!_io.panner().bypassed()); + } +} + +void +PannerUI::pan_reset () +{ +} + +void +PannerUI::effective_pan_display () +{ + if (_io.panner().empty()) { + return; + } + + switch (_io.n_outputs()) { + case 0: + case 1: + /* relax */ + break; + + case 2: + update_pan_bars (true); + break; + + default: + //panner->move_puck (pan_value (v, right), 0.5); + break; + } +} + +void +PannerUI::pan_changed (void *src) +{ + if (src == this) { + return; + } + + switch (_io.panner().size()) { + case 0: + panning_link_box.set_sensitive (false); + return; + case 1: + panning_link_box.set_sensitive (false); + break; + default: + panning_link_box.set_sensitive (true); + } + + uint32_t nouts = _io.n_outputs(); + + switch (nouts) { + case 0: + case 1: + /* relax */ + break; + + case 2: + update_pan_bars (false); + break; + + default: + // panner->move_puck (pan_value (pans[0], pans[1]), 0.5); + break; + } +} + +void +PannerUI::pan_adjustment_changed (uint32_t which) +{ + if (!in_pan_update && which < _io.panner().size()) { + + float xpos; + float val = pan_adjustments[which]->get_value (); + _io.panner()[which]->get_position (xpos); + + /* add a kinda-sorta detent for the middle */ + + if (val != 0.5 && Panner::equivalent (val, 0.5)) { + /* this is going to be reentrant, so just + return after it. + */ + + in_pan_update = true; + pan_adjustments[which]->set_value (0.5); + in_pan_update = false; + return; + } + + if (!Panner::equivalent (val, xpos)) { + + _io.panner()[which]->set_position (val); + /* XXX + the panner objects have no access to the session, + so do this here. ick. + */ + _session.set_dirty(); + } + } +} + +void +PannerUI::pan_value_changed (uint32_t which) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &PannerUI::pan_value_changed), which)); + + if (which < _io.panner().size()) { + float xpos; + float val = pan_adjustments[which]->get_value (); + + _io.panner()[which]->get_position (xpos); + + if (!Panner::equivalent (val, xpos)) { + in_pan_update = true; + pan_adjustments[which]->set_value (xpos); + in_pan_update = false; + } + } +} + +void +PannerUI::update_pan_bars (bool only_if_aplay) +{ + uint32_t n; + vector::iterator i; + + in_pan_update = true; + + /* this runs during automation playback, and moves the bar controllers + and/or pucks around. + */ + + for (i = pan_adjustments.begin(), n = 0; i != pan_adjustments.end(); ++i, ++n) { + float xpos, val; + + if (only_if_aplay) { + AutomationList& alist (_io.panner()[n]->automation()); + + if (!alist.automation_playback()) { + continue; + } + } + + _io.panner()[n]->get_effective_position (xpos); + val = (*i)->get_value (); + + if (!Panner::equivalent (val, xpos)) { + (*i)->set_value (xpos); + } + } + + in_pan_update = false; +} + +void +PannerUI::pan_printer (char *buf, uint32_t len, Adjustment* adj) +{ + float val = adj->get_value(); + + if (val == 0.0f) { + snprintf (buf, len, X_("L")); + } else if (val == 1.0f) { + snprintf (buf, len, X_("R")); + } else if (Panner::equivalent (val, 0.5f)) { + snprintf (buf, len, X_("C")); + } else { + /* don't print anything */ + buf[0] = '\0'; + } +} + +void +PannerUI::update_pan_sensitive () +{ + bool sensitive = !(_io.panner().automation_state() & Play); + + switch (_io.n_outputs()) { + case 0: + case 1: + break; + case 2: + for (vector::iterator i = pan_bars.begin(); i != pan_bars.end(); ++i) { + (*i)->set_sensitive (sensitive); + } + break; + default: + if (panner) { + panner->set_sensitive (sensitive); + } + break; + } +} + diff --git a/gtk2_ardour/panner_ui.h b/gtk2_ardour/panner_ui.h new file mode 100644 index 0000000000..4a4078bb74 --- /dev/null +++ b/gtk2_ardour/panner_ui.h @@ -0,0 +1,121 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_panner_ui_h__ +#define __ardour_gtk_panner_ui_h__ + +#include +#include +#include +#include + +#include "enums.h" + +class Panner2d; + +namespace ARDOUR { + class IO; + class Session; +} +namespace Gtkmmext { + class FastMeter; + class BarController; +} + +class PannerUI : public Gtk::HBox +{ + public: + PannerUI (ARDOUR::IO&, ARDOUR::Session&); + ~PannerUI (); + + void pan_changed (void *); + + void update_pan_sensitive (); + void update_gain_sensitive (); + + void set_width (Width); + void setup_pan (); + + void effective_pan_display (); + + void set_meter_strip_name (string name); + + private: + ARDOUR::IO& _io; + ARDOUR::Session& _session; + + bool ignore_toggle; + bool in_pan_update; + + Panner2d* panner; + + Gtk::VBox pan_bar_packer; + Gtk::Viewport panning_viewport; + Gtk::EventBox panning_up; + Gtk::Arrow panning_up_arrow; + Gtk::EventBox panning_down; + Gtk::Arrow panning_down_arrow; + Gtk::VBox pan_vbox; + Width _width; + + gint panning_scroll_button_press_event (GdkEventButton*, int32_t dir); + gint panning_scroll_button_release_event (GdkEventButton*, int32_t dir); + + Gtk::ToggleButton panning_link_button; + Gtk::Button panning_link_direction_button; + Gtk::HBox panning_link_box; + + gint panning_link_button_press (GdkEventButton*); + gint panning_link_button_release (GdkEventButton*); + void panning_link_direction_clicked (); + + vector pan_adjustments; + vector pan_bars; + + void pan_adjustment_changed (uint32_t which); + void pan_value_changed (uint32_t which); + void pan_printer (char* buf, uint32_t, Gtk::Adjustment*); + void update_pan_bars (bool only_if_aplay); + void update_pan_linkage (); + void update_pan_state (); + + void panner_changed (); + + void hide_pans (); + + void panner_moved (int which); + void panner_bypass_toggled (); + + gint start_pan_touch (GdkEventButton*); + gint end_pan_touch (GdkEventButton*); + + gint entry_focus_event (GdkEventFocus* ev); + + gint pan_button_event (GdkEventButton*, uint32_t which); + Gtk::Menu* pan_menu; + Gtk::CheckMenuItem* bypass_menu_item; + void build_pan_menu (uint32_t which); + void pan_mute (uint32_t which); + void pan_reset (); + void pan_bypass_toggle (); +}; + +#endif /* __ardour_gtk_panner_ui_h__ */ + diff --git a/gtk2_ardour/pixmaps/SConscript b/gtk2_ardour/pixmaps/SConscript new file mode 100644 index 0000000000..c532d3551a --- /dev/null +++ b/gtk2_ardour/pixmaps/SConscript @@ -0,0 +1,10 @@ +# -*- python -*- + +import os +import glob +pixmap_files = glob.glob('*.xpm') + +Import('env install_prefix') +env.Alias('install', env.Install(os.path.join(install_prefix, 'share/ardour/pixmaps'), pixmap_files)) + +env.Alias('tarball', env.Distribute(env['DISTTREE'], [ 'SConscript' ] + pixmap_files)) diff --git a/gtk2_ardour/pixmaps/hslider00.xpm b/gtk2_ardour/pixmaps/hslider00.xpm new file mode 100644 index 0000000000..47d40e1df4 --- /dev/null +++ b/gtk2_ardour/pixmaps/hslider00.xpm @@ -0,0 +1,179 @@ +/* XPM */ +static char * hslider00_xpm[] = { +"38 19 157 2", +" c None", +". c #8B8B8B", +"+ c #8C8C8C", +"@ c #949494", +"# c #3C3C3C", +"$ c #808080", +"% c #858585", +"& c #A7A7A7", +"* c #B8B8B8", +"= c #CCCCCC", +"- c #DBDBDB", +"; c #DEDEDE", +"> c #FFFFFF", +", c #E6E6E6", +"' c #E5E5E5", +") c #848484", +"! c #2A2A2A", +"~ c #383838", +"{ c #DFDFDF", +"] c #E2E2E2", +"^ c #CBCBCB", +"/ c #888888", +"( c #626262", +"_ c #090909", +": c #6C6C6C", +"< c #818181", +"[ c #A1A1A1", +"} c #ADADAD", +"| c #C7C7C7", +"1 c #D4D4D4", +"2 c #D9D9D9", +"3 c #D7D7D7", +"4 c #D1D1D1", +"5 c #D2D2D2", +"6 c #CFCFCF", +"7 c #DCDCDC", +"8 c #BBBBBB", +"9 c #696969", +"0 c #000000", +"a c #7C7C7C", +"b c #D8D8D8", +"c c #D5D5D5", +"d c #DADADA", +"e c #C5C5C5", +"f c #B1B1B1", +"g c #666666", +"h c #515151", +"i c #797979", +"j c #A8A8A8", +"k c #C8C8C8", +"l c #DDDDDD", +"m c #CACACA", +"n c #B9B9B9", +"o c #BDBDBD", +"p c #646464", +"q c #A2A2A2", +"r c #D0D0D0", +"s c #C2C2C2", +"t c #D6D6D6", +"u c #BEBEBE", +"v c #A6A6A6", +"w c #5D5D5D", +"x c #4A4A4A", +"y c #5C5C5C", +"z c #6D6D6D", +"A c #828282", +"B c #A3A3A3", +"C c #D3D3D3", +"D c #AFAFAF", +"E c #B6B6B6", +"F c #CDCDCD", +"G c #C0C0C0", +"H c #9B9B9B", +"I c #535353", +"J c #3D3D3D", +"K c #545454", +"L c #7B7B7B", +"M c #9E9E9E", +"N c #E7E7E7", +"O c #9F9F9F", +"P c #636363", +"Q c #BABABA", +"R c #919191", +"S c #4C4C4C", +"T c #4E4E4E", +"U c #787878", +"V c #999999", +"W c #BFBFBF", +"X c #E8E8E8", +"Y c #C3C3C3", +"Z c #989898", +"` c #C6C6C6", +" . c #ABABAB", +".. c #B5B5B5", +"+. c #8A8A8A", +"@. c #494949", +"#. c #595959", +"$. c #959595", +"%. c #C4C4C4", +"&. c #B4B4B4", +"*. c #616161", +"=. c #CECECE", +"-. c #B2B2B2", +";. c #555555", +">. c #929292", +",. c #8D8D8D", +"'. c #5E5E5E", +"). c #C9C9C9", +"!. c #A5A5A5", +"~. c #8F8F8F", +"{. c #BCBCBC", +"]. c #898989", +"^. c #B3B3B3", +"/. c #AEAEAE", +"(. c #B7B7B7", +"_. c #B0B0B0", +":. c #A9A9A9", +"<. c #AAAAAA", +"[. c #585858", +"}. c #7F7F7F", +"|. c #7D7D7D", +"1. c #565656", +"2. c #ACACAC", +"3. c #9C9C9C", +"4. c #878787", +"5. c #979797", +"6. c #505050", +"7. c #7A7A7A", +"8. c #8E8E8E", +"9. c #969696", +"0. c #6B6B6B", +"a. c #838383", +"b. c #A0A0A0", +"c. c #747474", +"d. c #757575", +"e. c #3F3F3F", +"f. c #727272", +"g. c #909090", +"h. c #717171", +"i. c #484848", +"j. c #4D4D4D", +"k. c #707070", +"l. c #686868", +"m. c #353535", +"n. c #656565", +"o. c #606060", +"p. c #5B5B5B", +"q. c #6A6A6A", +"r. c #5F5F5F", +"s. c #4B4B4B", +"t. c #373737", +"u. c #202020", +"v. c #131313", +"w. c #0B0B0B", +"x. c #060606", +"y. c #030303", +"z. c #010101", +" . + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ + # ", +"$ % & * = - ; > > > > > > > , ' > ) ! ~ % > { ; ] > > > > > > > > > ^ / ( _ ", +": < [ } | 1 - 2 3 3 4 4 5 5 6 7 8 9 0 0 a * b 7 c c 7 d c c - 2 4 e f g h 0 ", +"g i + j k c l 3 1 1 ^ = m m n l o p 0 0 a n 1 q r r ; s r r t f | u v w x 0 ", +"y z A B s t ' C l l m 6 ^ ^ & d D p 0 0 a E t q F F 7 q ^ ^ 5 f G 8 H I J 0 ", +"K p L M G b N 3 - - e ^ | | O b o P 0 0 a * b q ^ ^ - q | | 4 f n Q R S ~ 0 ", +"T w U V W d X b 2 2 G k Y Y Z b D ( 0 0 a * b q ^ ^ - q ` ` r ...n +.S ~ 0 ", +"@.#.U $.o - X b 3 3 8 %.W W R 3 &.*.0 0 a ..3 q m m d q ` ` =.& -...% S ~ 0 ", +"@.;.z >.8 7 X d c c E G Q Q ,.b f '.0 0 a -.c q ).).2 q ` ` = !.D f A S ~ 0 ", +"@.K z ~.n l X 2 C C f {.&.&.].2 &.w 0 0 a ^.C q k k b q m m = B /.} $ S ~ 0 ", +"@.K z + (.l { ; 4 4 } .././.% 2 E #.0 0 a _.4 q k k 3 q ).).= B } :.$ S ~ 0 ", +"@.I z +.E l l 7 r r <.D j j < 2 o [.0 0 a /.6 q | | c q ).).F q } & }.S ~ 0 ", +"@.I z ].E 7 - 3 6 6 & j q q |.2 E 1.0 0 a 2.= q ` ` 5 q k k F q } & }.S ~ 0 ", +"@.I z / E - b 5 = = !.[ 3.3.a 2 /.I 0 0 a :.| q s s =.q Y Y m q 2.& }.S ~ 0 ", +"@.I z 4.E l 7 b k ).@ 5.$.$.L t !.6.0 0 a !.G q o o ).q Q Q e q .j }.S ~ 0 ", +"@.I z 4.^.5 k Y o ^.~.+.+.+.7./.5.@.0 0 a V [ 3.v v &.8.B B -.q 9.+.0.S ~ 0 ", +"@.I ( a.3.b.~.a.|.|.7.7.c.% i c.d.e.0 0 a + ~.d.a a ].f.7.7.g.|.i h.P i.~ 0 ", +"i.j.P ( 0.: : 0.k.: 9 ( w l.p 0.P m.0 0 i.n.g o.P w p.p p.q.'.r.p *.r.p.S 0 ", +" o.s.t.u.v.w.x.y.z.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "}; diff --git a/gtk2_ardour/pixmaps/hslider01.xpm b/gtk2_ardour/pixmaps/hslider01.xpm new file mode 100644 index 0000000000..65b51b7310 --- /dev/null +++ b/gtk2_ardour/pixmaps/hslider01.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char * hslider01_xpm[] = { +"149 20 2 1", +" c None", +". c #000000", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +".....................................................................................................................................................", +".....................................................................................................................................................", +".....................................................................................................................................................", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/gtk2_ardour/pixmaps/set-next-button.xpm b/gtk2_ardour/pixmaps/set-next-button.xpm new file mode 100644 index 0000000000..ab1a47b08b --- /dev/null +++ b/gtk2_ardour/pixmaps/set-next-button.xpm @@ -0,0 +1,1833 @@ +/* XPM */ +static char * set_next_button_xpm[] = { +"131 34 1796 2", +" c None", +". c #526770", +"+ c #52666E", +"@ c #4D5F67", +"# c #495A62", +"$ c #3C5159", +"% c #384D56", +"& c #344954", +"* c #334853", +"= c #334852", +"- c #334750", +"; c #33474F", +"> c #33474C", +", c #33484F", +"' c #334950", +") c #33484E", +"! c #33484D", +"~ c #33464C", +"{ c #33464B", +"] c #33454A", +"^ c #334349", +"/ c #334348", +"( c #334445", +"_ c #334244", +": c #334144", +"< c #304044", +"[ c #2F4044", +"} c #2F4145", +"| c #2F4246", +"1 c #2F3E44", +"2 c #2F3F44", +"3 c #2D3F42", +"4 c #2C3E42", +"5 c #2A3C40", +"6 c #2A3D40", +"7 c #2B3F40", +"8 c #2E3E40", +"9 c #2F3E40", +"0 c #2C3E40", +"a c #2B3E40", +"b c #2A3E40", +"c c #2A3B40", +"d c #2A3A40", +"e c #2A3A41", +"f c #2A3B41", +"g c #2A3B3F", +"h c #2A3A3F", +"i c #2A383B", +"j c #2A393B", +"k c #2A3B3E", +"l c #2A393C", +"m c #2A393A", +"n c #2A383A", +"o c #28383A", +"p c #27383A", +"q c #25393A", +"r c #25383B", +"s c #25363C", +"t c #25343B", +"u c #25333A", +"v c #25343A", +"w c #25353A", +"x c #25363A", +"y c #25373A", +"z c #243538", +"A c #213133", +"B c #203032", +"C c #203031", +"D c #202E31", +"E c #1F2D31", +"F c #1D2D31", +"G c #1E2E31", +"H c #202F34", +"I c #223036", +"J c #2A3940", +"K c #314048", +"L c #48565E", +"M c #4D5A62", +"N c #485E63", +"O c #40575C", +"P c #2E4247", +"Q c #26383D", +"R c #1E3136", +"S c #1E3036", +"T c #1F3138", +"U c #1E3138", +"V c #1D3138", +"W c #1F3139", +"X c #203139", +"Y c #203035", +"Z c #202F32", +"` c #1F2E31", +" . c #1F2E30", +".. c #1F2C30", +"+. c #1E2C30", +"@. c #1C2C30", +"#. c #1A2C30", +"$. c #192C30", +"%. c #1B2C30", +"&. c #1B2D2F", +"*. c #1C2D2E", +"=. c #1D2C2B", +"-. c #1B2C2A", +";. c #192C2A", +">. c #1A2C2A", +",. c #1D2C2A", +"'. c #1E2D2A", +"). c #1B2C2B", +"!. c #192C2B", +"~. c #1B2D2A", +"{. c #1A2D2A", +"]. c #1D2D2A", +"^. c #1B2C2C", +"/. c #1C2C2D", +"(. c #202E2F", +"_. c #1E2D2F", +":. c #1D2D2F", +"<. c #1B2B2D", +"[. c #1A2B2C", +"}. c #1E2D2D", +"|. c #1F2C2F", +"1. c #1E2B2D", +"2. c #1F2B2C", +"3. c #202C2A", +"4. c #202D2B", +"5. c #202B2B", +"6. c #202B2A", +"7. c #1E2B28", +"8. c #1E2B29", +"9. c #1D2B2B", +"0. c #1F2D2E", +"a. c #1B2A2B", +"b. c #1A2A2D", +"c. c #192B2F", +"d. c #1A2C2C", +"e. c #192C29", +"f. c #1C2C2A", +"g. c #1F2A2A", +"h. c #1E292A", +"i. c #1D292A", +"j. c #1C292A", +"k. c #1B292A", +"l. c #1B2A2A", +"m. c #1A2A2A", +"n. c #1A2A2B", +"o. c #19292E", +"p. c #19292D", +"q. c #1A292E", +"r. c #1B292F", +"s. c #1A2A2C", +"t. c #1A2B2A", +"u. c #192C28", +"v. c #1D2D2C", +"w. c #1E2E2F", +"x. c #202E32", +"y. c #203133", +"z. c #1F2F32", +"A. c #1E2E33", +"B. c #1F2F34", +"C. c #233338", +"D. c #35444A", +"E. c #39474E", +"F. c #3B4E51", +"G. c #2C3E41", +"H. c #203436", +"I. c #1C3031", +"J. c #1F3031", +"K. c #1F3032", +"L. c #1C3032", +"M. c #1A3032", +"N. c #1B3033", +"O. c #1D3033", +"P. c #1F2E34", +"Q. c #1D2C33", +"R. c #1C282E", +"S. c #1B262B", +"T. c #1A262A", +"U. c #192629", +"V. c #1A282A", +"W. c #1D2A2A", +"X. c #1E2B2A", +"Y. c #1C2A2A", +"Z. c #1D2B2A", +"`. c #1E2B2B", +" + c #1E2B2F", +".+ c #1E2B2C", +"++ c #202D2A", +"@+ c #212D2A", +"#+ c #1F2C2A", +"$+ c #212C2A", +"%+ c #212B2A", +"&+ c #212B2B", +"*+ c #212B2E", +"=+ c #212B2F", +"-+ c #202B2F", +";+ c #202C2E", +">+ c #212D2C", +",+ c #212C2E", +"'+ c #212D2F", +")+ c #212F2D", +"!+ c #212F2C", +"~+ c #212F2B", +"{+ c #212F29", +"]+ c #202E29", +"^+ c #1E2C28", +"/+ c #1F2D2B", +"(+ c #212F2E", +"_+ c #212E2F", +":+ c #212C2F", +"<+ c #202C2F", +"[+ c #1E2C2F", +"}+ c #1F2E2F", +"|+ c #202F2F", +"1+ c #212F2F", +"2+ c #1F2F2E", +"3+ c #1E2E2D", +"4+ c #222F2E", +"5+ c #24302F", +"6+ c #222E30", +"7+ c #202D30", +"8+ c #1E2D30", +"9+ c #1E2E30", +"0+ c #1E2F30", +"a+ c #212F30", +"b+ c #232F30", +"c+ c #272F30", +"d+ c #262F30", +"e+ c #242F30", +"f+ c #223030", +"g+ c #213030", +"h+ c #1F3230", +"i+ c #203230", +"j+ c #223230", +"k+ c #23312E", +"l+ c #24312D", +"m+ c #25322E", +"n+ c #26322F", +"o+ c #23302C", +"p+ c #1E2C27", +"q+ c #1C2A28", +"r+ c #1A2928", +"s+ c #1A282B", +"t+ c #1D292E", +"u+ c #1F2C31", +"v+ c #253237", +"w+ c #263539", +"x+ c #26373A", +"y+ c #223639", +"z+ c #213538", +"A+ c #223338", +"B+ c #233339", +"C+ c #26343A", +"D+ c #213337", +"E+ c #223438", +"F+ c #24363A", +"G+ c #313F44", +"H+ c #334146", +"I+ c #314244", +"J+ c #223435", +"K+ c #213134", +"L+ c #203034", +"M+ c #223336", +"N+ c #243439", +"O+ c #243539", +"P+ c #243639", +"Q+ c #24353A", +"R+ c #23343A", +"S+ c #203136", +"T+ c #182628", +"U+ c #19252A", +"V+ c #1A262B", +"W+ c #212E33", +"X+ c #263338", +"Y+ c #2D3A40", +"Z+ c #313E43", +"`+ c #364346", +" @ c #384548", +".@ c #394749", +"+@ c #394649", +"@@ c #39494A", +"#@ c #39484A", +"$@ c #394849", +"%@ c #39484C", +"&@ c #39484D", +"*@ c #39494D", +"=@ c #394A4D", +"-@ c #3B4A4D", +";@ c #3C4A4D", +">@ c #3D4A4D", +",@ c #3E4A4D", +"'@ c #3E4C4D", +")@ c #3D4C4D", +"!@ c #3D4B4D", +"~@ c #3E4B4E", +"{@ c #3F4B4F", +"]@ c #414D51", +"^@ c #414E52", +"/@ c #414F50", +"(@ c #415051", +"_@ c #3F4D50", +":@ c #3E4C4F", +"<@ c #404E51", +"[@ c #414F52", +"}@ c #415155", +"|@ c #415055", +"1@ c #435055", +"2@ c #455257", +"3@ c #445257", +"4@ c #425256", +"5@ c #435255", +"6@ c #455255", +"7@ c #455256", +"8@ c #455359", +"9@ c #455259", +"0@ c #455459", +"a@ c #45555A", +"b@ c #45545D", +"c@ c #45545E", +"d@ c #45555E", +"e@ c #45555F", +"f@ c #465661", +"g@ c #485762", +"h@ c #495862", +"i@ c #4A5862", +"j@ c #4B5862", +"k@ c #4D5861", +"l@ c #4C585E", +"m@ c #4A585B", +"n@ c #47585B", +"o@ c #45585C", +"p@ c #465960", +"q@ c #475961", +"r@ c #4B5A62", +"s@ c #4C5A62", +"t@ c #4D5962", +"u@ c #4D5B62", +"v@ c #4A595F", +"w@ c #425356", +"x@ c #3B4B4F", +"y@ c #344347", +"z@ c #273939", +"A@ c #203332", +"B@ c #1B2C2D", +"C@ c #1F3033", +"D@ c #2B3C42", +"E@ c #304047", +"F@ c #35444C", +"G@ c #2F4347", +"H@ c #2D4145", +"I@ c #2E3E45", +"J@ c #2E3D45", +"K@ c #2F3D45", +"L@ c #2E3B43", +"M@ c #2D3A41", +"N@ c #2C3B42", +"O@ c #2D3C44", +"P@ c #34434B", +"Q@ c #36444D", +"R@ c #324548", +"S@ c #27393C", +"T@ c #2A383F", +"U@ c #2B3940", +"V@ c #2E3D43", +"W@ c #303F45", +"X@ c #334149", +"Y@ c #33424A", +"Z@ c #33424B", +"`@ c #29383C", +" # c #223232", +".# c #182824", +"+# c #22302F", +"@# c #2B3838", +"## c #434F57", +"$# c #515C67", +"%# c #606D7B", +"&# c #667583", +"*# c #6C7D8C", +"=# c #71818E", +"-# c #748390", +";# c #728290", +"># c #718290", +",# c #718391", +"'# c #718390", +")# c #718491", +"!# c #718592", +"~# c #718593", +"{# c #728693", +"]# c #728792", +"^# c #768791", +"/# c #788891", +"(# c #7A8C93", +"_# c #7A8B93", +":# c #7A8993", +"<# c #798894", +"[# c #788794", +"}# c #798996", +"|# c #798B98", +"1# c #7A8D9C", +"2# c #7A8C9C", +"3# c #7A8B9B", +"4# c #798997", +"5# c #788895", +"6# c #7A8C99", +"7# c #7B8D9B", +"8# c #7D8E9D", +"9# c #7C8D9D", +"0# c #7A8B9A", +"a# c #7B8C9D", +"b# c #7D8D9F", +"c# c #808FA2", +"d# c #8192A3", +"e# c #8193A4", +"f# c #8293A4", +"g# c #8292A4", +"h# c #8394A4", +"i# c #8395A4", +"j# c #8697A8", +"k# c #8393A4", +"l# c #8192A2", +"m# c #7F91A0", +"n# c #8294A3", +"o# c #8495A5", +"p# c #8496A7", +"q# c #8496A8", +"r# c #8596A8", +"s# c #8497AA", +"t# c #8597AA", +"u# c #8897A9", +"v# c #8997AA", +"w# c #8A98AC", +"x# c #8799AC", +"y# c #8699AC", +"z# c #8398AA", +"A# c #8297A8", +"B# c #8296A5", +"C# c #8497A8", +"D# c #8395A6", +"E# c #8496A5", +"F# c #8194A2", +"G# c #7B909C", +"H# c #738790", +"I# c #6B7D85", +"J# c #4F5F63", +"K# c #3D4E4E", +"L# c #203430", +"M# c #223533", +"N# c #364449", +"O# c #3B494F", +"P# c #404D54", +"Q# c #3C4D54", +"R# c #3A4C54", +"S# c #3A4852", +"T# c #3A4751", +"U# c #39464E", +"V# c #36434B", +"W# c #324049", +"X# c #32404A", +"Y# c #35464E", +"Z# c #36474F", +"`# c #3A4C51", +" $ c #314348", +".$ c #354249", +"+$ c #38434B", +"@$ c #3A474F", +"#$ c #3D4952", +"$$ c #404B56", +"%$ c #404B57", +"&$ c #404B58", +"*$ c #3F4C57", +"=$ c #3C4B52", +"-$ c #304042", +";$ c #273736", +">$ c #192A24", +",$ c #2E3C39", +"'$ c #3E4A4A", +")$ c #5F6974", +"!$ c #717B8C", +"~$ c #8795AC", +"{$ c #8F9FB7", +"]$ c #95A9C2", +"^$ c #98AAC3", +"/$ c #9AABC3", +"($ c #9AABC2", +"_$ c #9BACC3", +":$ c #9DAFC5", +"<$ c #9EAFC6", +"[$ c #9EAEC6", +"}$ c #9EADC6", +"|$ c #9DADC6", +"1$ c #9CADC6", +"2$ c #9AADC5", +"3$ c #99ADC4", +"4$ c #99ACC4", +"5$ c #99ACC3", +"6$ c #9BAEC3", +"7$ c #9BAFC4", +"8$ c #9CB1C8", +"9$ c #9CB0C8", +"0$ c #9BAEC7", +"a$ c #98ABC4", +"b$ c #97AAC3", +"c$ c #9BADC6", +"d$ c #9DAEC8", +"e$ c #9FB0CB", +"f$ c #9EAFCB", +"g$ c #9CADCA", +"h$ c #9BADC9", +"i$ c #A0B1CC", +"j$ c #9EB1CE", +"k$ c #9DAFCB", +"l$ c #9BADC8", +"m$ c #9BACC5", +"n$ c #9BADC4", +"o$ c #9BADC5", +"p$ c #9BADCA", +"q$ c #9CADC9", +"r$ c #9DADC8", +"s$ c #9EAFCA", +"t$ c #9EB0CB", +"u$ c #9EAFC9", +"v$ c #9EAEC8", +"w$ c #9DACC7", +"x$ c #9DADC7", +"y$ c #9EAFC8", +"z$ c #9FB1C7", +"A$ c #9FB2C7", +"B$ c #9FB3C9", +"C$ c #9EB2C9", +"D$ c #9BAFC7", +"E$ c #9AAFC5", +"F$ c #99AEC3", +"G$ c #9AB0C6", +"H$ c #9AB1C8", +"I$ c #9BB0CA", +"J$ c #99AEC8", +"K$ c #98ACC6", +"L$ c #99AAC3", +"M$ c #9AABC4", +"N$ c #99ADC5", +"O$ c #98ADC5", +"P$ c #95ABC3", +"Q$ c #94AAC3", +"R$ c #94A9C3", +"S$ c #95A9C3", +"T$ c #96A9C3", +"U$ c #98ACC5", +"V$ c #99ADC6", +"W$ c #99AEC7", +"X$ c #9AAFC7", +"Y$ c #9DB1C6", +"Z$ c #95A8B9", +"`$ c #8D9EAB", +" % c #6D7F85", +".% c #57696A", +"+% c #293E39", +"@% c #273B38", +"#% c #425259", +"$% c #485760", +"%% c #45575F", +"&% c #44565D", +"*% c #42515A", +"=% c #414F59", +"-% c #404D58", +";% c #3D4A54", +">% c #3A4750", +",% c #384550", +"'% c #384551", +")% c #3B4754", +"!% c #3C4855", +"~% c #3C4F56", +"{% c #34484F", +"]% c #3A4A53", +"^% c #3E4C56", +"/% c #425059", +"(% c #45525B", +"_% c #49545E", +":% c #4A555E", +"<% c #49565E", +"[% c #45535B", +"}% c #37454B", +"|% c #2E3C3E", +"1% c #202E2B", +"2% c #394344", +"3% c #4D5459", +"4% c #6C7484", +"5% c #7C869A", +"6% c #8D9AB2", +"7% c #909EB7", +"8% c #919FB9", +"9% c #8F9DB7", +"0% c #8E9BB6", +"a% c #8A9AB5", +"b% c #8899B4", +"c% c #8798B4", +"d% c #8797B4", +"e% c #8796B4", +"f% c #8696B4", +"g% c #8596B4", +"h% c #8395B4", +"i% c #8395B3", +"j% c #8395B1", +"k% c #8395B2", +"l% c #8596B0", +"m% c #8596B1", +"n% c #8696B2", +"o% c #8495B0", +"p% c #8394B0", +"q% c #8393B0", +"r% c #8495B4", +"s% c #8595B4", +"t% c #8695B4", +"u% c #8496B0", +"v% c #8395AB", +"w% c #8394AB", +"x% c #8393AB", +"y% c #8392AB", +"z% c #8494AC", +"A% c #8695AE", +"B% c #8796AF", +"C% c #8594AE", +"D% c #8593AD", +"E% c #8595AE", +"F% c #8594AC", +"G% c #8594AB", +"H% c #8396AB", +"I% c #8397AB", +"J% c #8395AD", +"K% c #8394AE", +"L% c #8395B0", +"M% c #8394AF", +"N% c #8393AD", +"O% c #8392AC", +"P% c #8193A9", +"Q% c #8293A9", +"R% c #8394A9", +"S% c #8495A7", +"T% c #76878E", +"U% c #68787B", +"V% c #374844", +"W% c #324340", +"X% c #405153", +"Y% c #45585D", +"Z% c #4A5D65", +"`% c #495C63", +" & c #485B62", +".& c #485962", +"+& c #465660", +"@& c #43535D", +"#& c #40505A", +"$& c #3E4D57", +"%& c #3A4953", +"&& c #3A4853", +"*& c #3D4B56", +"=& c #3E4C57", +"-& c #44545C", +";& c #3E4E57", +">& c #404F59", +",& c #42515B", +"'& c #49575E", +")& c #4A5960", +"!& c #4A5A62", +"~& c #4A5B62", +"{& c #47585E", +"]& c #303D41", +"^& c #252E31", +"/& c #3D464E", +"(& c #505964", +"_& c #6B7785", +":& c #778495", +"<& c #808EA4", +"[& c #8290A8", +"}& c #8390A9", +"|& c #838FA7", +"1& c #828EA6", +"2& c #808CA4", +"3& c #808DA4", +"4& c #808FA4", +"5& c #7D8DA3", +"6& c #7B8CA2", +"7& c #7B8DA4", +"8& c #7B8CA4", +"9& c #7B8CA3", +"0& c #7B8DA3", +"a& c #7C8DA4", +"b& c #8290A4", +"c& c #838FA4", +"d& c #838EA4", +"e& c #838DA4", +"f& c #818DA2", +"g& c #808DA1", +"h& c #828DA3", +"i& c #828FA3", +"j& c #818EA2", +"k& c #7F8CA0", +"l& c #7E8CA0", +"m& c #7F8DA1", +"n& c #7F8DA2", +"o& c #7F8EA3", +"p& c #8090A6", +"q& c #8090A7", +"r& c #8090A9", +"s& c #8090A8", +"t& c #808FA6", +"u& c #808FA5", +"v& c #808EA3", +"w& c #808DA2", +"x& c #808CA1", +"y& c #808EA0", +"z& c #7F8E9D", +"A& c #75848D", +"B& c #69777C", +"C& c #394647", +"D& c #344142", +"E& c #415053", +"F& c #46585E", +"G& c #4A5F67", +"H& c #4A5E67", +"I& c #4A5D66", +"J& c #475B61", +"K& c #42585F", +"L& c #41545B", +"M& c #415058", +"N& c #3D4C54", +"O& c #3D4B54", +"P& c #404D56", +"Q& c #414E57", +"R& c #45595E", +"S& c #41545A", +"T& c #42555B", +"U& c #43565C", +"V& c #4A5D64", +"W& c #4B6067", +"X& c #4D6068", +"Y& c #4E6068", +"Z& c #4E5F67", +"`& c #37484D", +" * c #2E3E42", +".* c #253035", +"+* c #3D464F", +"@* c #4F5863", +"#* c #677684", +"$* c #738494", +"%* c #818DA3", +"&* c #828CA4", +"** c #7C89A2", +"=* c #7B8AA2", +"-* c #7B8AA1", +";* c #7B8BA2", +">* c #7B89A1", +",* c #7B89A0", +"'* c #7B899F", +")* c #7B889C", +"!* c #7B889B", +"~* c #7B8799", +"{* c #7B879A", +"]* c #7C8AA2", +"^* c #7F8CA2", +"/* c #808CA2", +"(* c #818CA2", +"_* c #7E8C9F", +":* c #7D8C9E", +"<* c #7E8D9F", +"[* c #7D8D9E", +"}* c #7B8B9C", +"|* c #7B8C9C", +"1* c #7D8C9D", +"2* c #7F8C9F", +"3* c #808B9F", +"4* c #808A9F", +"5* c #7F8B9F", +"6* c #7C8C9D", +"7* c #7C8B9D", +"8* c #7C8A9C", +"9* c #7B889A", +"0* c #7B8697", +"a* c #7B8696", +"b* c #7B8797", +"c* c #7B8999", +"d* c #7B8C9E", +"e* c #7B8BA0", +"f* c #7B8BA1", +"g* c #7B8DA2", +"h* c #7B8B9F", +"i* c #7B8A9D", +"j* c #7B8A9C", +"k* c #7C8A9D", +"l* c #7B8B9B", +"m* c #7B8B99", +"n* c #74838B", +"o* c #3C4647", +"p* c #364142", +"q* c #3E5053", +"r* c #45575E", +"s* c #4A5D67", +"t* c #4A5D68", +"u* c #4A5C63", +"v* c #495962", +"w* c #45565E", +"x* c #41535B", +"y* c #3D4E56", +"z* c #404E57", +"A* c #475960", +"B* c #495E64", +"C* c #4C616A", +"D* c #4D616A", +"E* c #4B5B62", +"F* c #374849", +"G* c #2F3F3F", +"H* c #263336", +"I* c #39474B", +"J* c #48575D", +"K* c #667684", +"L* c #748495", +"M* c #7C8B9F", +"N* c #7D8CA0", +"O* c #7E8B9F", +"P* c #7D8B9E", +"Q* c #7B899C", +"R* c #7B8B9D", +"S* c #7B8A9E", +"T* c #7B8595", +"U* c #7B8594", +"V* c #7B8695", +"W* c #7B8798", +"X* c #7B8698", +"Y* c #7B8998", +"Z* c #7C8999", +"`* c #7E899A", +" = c #7C8A9A", +".= c #7B8B9A", +"+= c #7B899A", +"@= c #7B8A9A", +"#= c #7D8898", +"$= c #7C8797", +"%= c #7C8696", +"&= c #7B8897", +"*= c #7B899B", +"== c #7B8D9C", +"-= c #74828B", +";= c #3D4647", +">= c #4A5C67", +",= c #4A5E69", +"'= c #4A5F69", +")= c #4A5F65", +"!= c #4A5E63", +"~= c #475860", +"{= c #44555F", +"]= c #3E4F57", +"^= c #3D4D54", +"/= c #425962", +"(= c #3C535C", +"_= c #435760", +":= c #475A62", +"<= c #4A6065", +"[= c #4A6166", +"}= c #4A6066", +"|= c #4A5F66", +"1= c #37494C", +"2= c #304144", +"3= c #29383B", +"4= c #3A484D", +"5= c #48565C", +"6= c #647481", +"7= c #718291", +"8= c #798A9A", +"9= c #7A8B9C", +"0= c #7A899A", +"a= c #798998", +"b= c #73828B", +"c= c #4A5D69", +"d= c #4A5D62", +"e= c #485960", +"f= c #46555F", +"g= c #3F4F57", +"h= c #45595F", +"i= c #40555C", +"j= c #445960", +"k= c #475C62", +"l= c #4B5F65", +"m= c #4D6066", +"n= c #4F6169", +"o= c #4C6067", +"p= c #4A5D63", +"q= c #47595E", +"r= c #3B494E", +"s= c #344145", +"t= c #29383A", +"u= c #3A4A50", +"v= c #485861", +"w= c #64737F", +"x= c #71808D", +"y= c #7A889A", +"z= c #7B869C", +"A= c #7B879C", +"B= c #8190A2", +"C= c #8E9EB0", +"D= c #8E9DAF", +"E= c #8E9DAE", +"F= c #8E9DAD", +"G= c #8E9BAA", +"H= c #8793A2", +"I= c #818C9B", +"J= c #818E9F", +"K= c #8797A9", +"L= c #8E9DB0", +"M= c #8D9DAF", +"N= c #7B859C", +"O= c #7A8A98", +"P= c #69777D", +"Q= c #3D474D", +"R= c #364148", +"S= c #3C4D55", +"T= c #42555D", +"U= c #475C63", +"V= c #495F63", +"W= c #4A6063", +"X= c #4A5E62", +"Y= c #485A60", +"Z= c #46575F", +"`= c #3F5159", +" - c #3D4E57", +".- c #404E59", +"+- c #414E5A", +"@- c #455A5F", +"#- c #41565C", +"$- c #455A60", +"%- c #495E65", +"&- c #4A6067", +"*- c #4B616A", +"=- c #344245", +"-- c #293A39", +";- c #3B4C4F", +">- c #495A61", +",- c #65727D", +"'- c #727D8B", +")- c #7A8598", +"!- c #7B879B", +"~- c #7B859B", +"{- c #A2B2C4", +"]- c #B6C9D8", +"^- c #7A899B", +"/- c #8E9EAF", +"(- c #A2B2C1", +"_- c #9BAAB9", +":- c #7C8796", +"<- c #7D8897", +"[- c #818C9C", +"}- c #7B8596", +"|- c #9BAABB", +"1- c #95A4B6", +"2- c #7B8896", +"3- c #74828C", +"4- c #6A777F", +"5- c #3F494E", +"6- c #374448", +"7- c #3D4F55", +"8- c #42565C", +"9- c #475B62", +"0- c #495F62", +"a- c #4A6163", +"b- c #4C5F65", +"c- c #42535B", +"d- c #40515A", +"e- c #41505A", +"f- c #455B5F", +"g- c #41575C", +"h- c #455860", +"i- c #4A616A", +"j- c #4A5C61", +"k- c #47585D", +"l- c #3B484E", +"m- c #344146", +"n- c #293A3B", +"o- c #3C4C50", +"p- c #4B5A61", +"q- c #66717D", +"r- c #727C8B", +"s- c #7A8397", +"t- c #7B859A", +"u- c #95A3B3", +"v- c #A2B2C3", +"w- c #8E9CAF", +"x- c #9BABBB", +"y- c #798797", +"z- c #778594", +"A- c #8D9BAC", +"B- c #A8B9C9", +"C- c #A8B9C8", +"D- c #AFC1D0", +"E- c #84909F", +"F- c #7C8695", +"G- c #9BAABA", +"H- c #818C9E", +"I- c #818EA1", +"J- c #8D9CAC", +"K- c #8E9CAC", +"L- c #8E9BAE", +"M- c #7B8598", +"N- c #74828E", +"O- c #6A7781", +"P- c #3F4A4E", +"Q- c #394548", +"R- c #405055", +"S- c #45565C", +"T- c #4A5F62", +"U- c #4C6066", +"V- c #4B5E65", +"W- c #41515A", +"X- c #3A494F", +"Y- c #485661", +"Z- c #656F7D", +"`- c #727B8B", +" ; c #7A8297", +".; c #7B849A", +"+; c #7B8597", +"@; c #8F9CAB", +"#; c #8E9BAB", +"$; c #8E9AAA", +"%; c #7B8294", +"&; c #7B8496", +"*; c #7B8A97", +"=; c #74828A", +"-; c #6A777D", +";; c #394448", +">; c #4A6062", +",; c #4A5E64", +"'; c #41535A", +"); c #4D6067", +"!; c #4F616A", +"~; c #4C6167", +"{; c #4A6165", +"]; c #495D63", +"^; c #3A484E", +"/; c #334145", +"(; c #3A484C", +"_; c #48555B", +":; c #646F7B", +"<; c #717B8A", +"[; c #7A8396", +"}; c #7B8499", +"|; c #7B8599", +"1; c #95A3B2", +"2; c #7B8494", +"3; c #8D99AA", +"4; c #788194", +"5; c #798694", +"6; c #73818C", +"7; c #6A7780", +"8; c #3F4B4E", +"9; c #384648", +"0; c #3F5155", +"a; c #4A5F63", +"b; c #485A61", +"c; c #46585F", +"d; c #445359", +"e; c #4A6167", +"f; c #465D63", +"g; c #42575E", +"h; c #36464E", +"i; c #303F47", +"j; c #29383E", +"k; c #38464D", +"l; c #636D79", +"m; c #707A88", +"n; c #798292", +"o; c #7B8495", +"p; c #7B8394", +"q; c #768394", +"r; c #798494", +"s; c #74828D", +"t; c #697881", +"u; c #3D4D4E", +"v; c #364748", +"w; c #3E5155", +"x; c #4A5E68", +"y; c #4A5F6A", +"z; c #4A5E6A", +"A; c #46595F", +"B; c #42545A", +"C; c #425258", +"D; c #455557", +"E; c #465557", +"F; c #37494E", +"G; c #304147", +"H; c #626D79", +"I; c #6F7A88", +"J; c #788192", +"K; c #7A8394", +"L; c #3D4D50", +"M; c #36474A", +"N; c #3E5156", +"O; c #45565D", +"P; c #4A5D6A", +"Q; c #465C5F", +"R; c #42595C", +"S; c #475A60", +"T; c #495C62", +"U; c #4A5E65", +"V; c #606D79", +"W; c #6D7988", +"X; c #748092", +"Y; c #778294", +"Z; c #7A8294", +"`; c #7B8194", +" > c #74818D", +".> c #697882", +"+> c #36474E", +"@> c #3E5157", +"#> c #4A5C65", +"$> c #465C63", +"%> c #435960", +"&> c #4A5C62", +"*> c #4A6169", +"=> c #475A5E", +"-> c #455159", +";> c #5D6C79", +">> c #6A7888", +",> c #768092", +"'> c #798294", +")> c #788294", +"!> c #758194", +"~> c #778194", +"{> c #798194", +"]> c #7A8194", +"^> c #3D4D55", +"/> c #4A5C64", +"(> c #42595F", +"_> c #465A61", +":> c #485C62", +"<> c #4A6064", +"[> c #4A6168", +"}> c #47595F", +"|> c #37494F", +"1> c #304247", +"2> c #29393D", +"3> c #35464C", +"4> c #405159", +"5> c #5E6C79", +"6> c #6C7988", +"7> c #778292", +"8> c #7A8494", +"9> c #748194", +"0> c #748294", +"a> c #778394", +"b> c #A2B1C1", +"c> c #808B9B", +"d> c #9AAAB9", +"e> c #7A8594", +"f> c #A1B1C1", +"g> c #8B9AAA", +"h> c #758394", +"i> c #768494", +"j> c #778494", +"k> c #788494", +"l> c #798393", +"m> c #788293", +"n> c #727F8B", +"o> c #687680", +"p> c #3F4D55", +"q> c #39484F", +"r> c #3F515A", +"s> c #455761", +"t> c #4A5C66", +"u> c #415159", +"v> c #445458", +"w> c #41585C", +"x> c #496062", +"y> c #4A6164", +"z> c #47585F", +"A> c #374A50", +"B> c #304347", +"C> c #293C3C", +"D> c #35484C", +"E> c #405259", +"F> c #616D79", +"G> c #6F7988", +"H> c #788394", +"I> c #8391A2", +"J> c #7D8B9B", +"K> c #758294", +"L> c #A0B1C1", +"M> c #8999AA", +"N> c #738394", +"O> c #738294", +"P> c #758494", +"Q> c #798594", +"R> c #768393", +"S> c #748292", +"T> c #707E8A", +"U> c #68757E", +"V> c #424B52", +"W> c #3B464E", +"X> c #3F515C", +"Y> c #455864", +"Z> c #475A5F", +"`> c #374B50", +" , c #304449", +"., c #293C40", +"+, c #36484E", +"@, c #415259", +"#, c #738194", +"$, c #788594", +"%, c #748393", +"&, c #748392", +"*, c #737E8A", +"=, c #6B757E", +"-, c #434B52", +";, c #455964", +">, c #4A6068", +",, c #455C5F", +"', c #41595C", +"), c #394C52", +"!, c #32454B", +"~, c #293C41", +"{, c #38484E", +"], c #636C76", +"^, c #707884", +"/, c #798192", +"(, c #768294", +"_, c #748394", +":, c #768594", +"<, c #768493", +"[, c #788492", +"}, c #757E8A", +"|, c #6C757F", +"1, c #444F54", +"2, c #3C4950", +"3, c #40515C", +"4, c #455963", +"5, c #4A5F68", +"6, c #455C64", +"7, c #415962", +"8, c #455A62", +"9, c #3B4C54", +"0, c #34454C", +"a, c #778393", +"b, c #788393", +"c, c #788493", +"d, c #758392", +"e, c #727E8A", +"f, c #6A757F", +"g, c #444E54", +"h, c #3C494F", +"i, c #405157", +"j, c #455660", +"k, c #4A5B67", +"l, c #465E62", +"m, c #425A5E", +"n, c #475C61", +"o, c #495E62", +"p, c #4A5F64", +"q, c #394C55", +"r, c #33454B", +"s, c #2C3A3D", +"t, c #444E52", +"u, c #616C73", +"v, c #6E7983", +"w, c #768191", +"x, c #778293", +"y, c #778192", +"z, c #798293", +"A, c #7A8293", +"B, c #798493", +"C, c #748192", +"D, c #738192", +"E, c #738291", +"F, c #738392", +"G, c #748492", +"H, c #758492", +"I, c #748493", +"J, c #768293", +"K, c #758192", +"L, c #778092", +"M, c #788092", +"N, c #788093", +"O, c #778094", +"P, c #768094", +"Q, c #758094", +"R, c #7A8393", +"S, c #7A8492", +"T, c #7B828F", +"U, c #7A838E", +"V, c #77848D", +"W, c #76838E", +"X, c #75828E", +"Y, c #75828F", +"Z, c #75818F", +"`, c #73838D", +" ' c #6F7D85", +".' c #66737C", +"+' c #394651", +"@' c #3E5057", +"#' c #45585E", +"$' c #4C6267", +"%' c #4D6269", +"&' c #465761", +"*' c #42535D", +"=' c #41525B", +"-' c #41545E", +";' c #41555E", +">' c #465E63", +",' c #435A60", +"'' c #485C61", +")' c #475B60", +"!' c #394B52", +"~' c #324348", +"{' c #354247", +"]' c #404B50", +"^' c #5C6971", +"/' c #697681", +"(' c #737F8E", +"_' c #758191", +":' c #768194", +"<' c #798394", +"[' c #768192", +"}' c #737F90", +"|' c #738190", +"1' c #758193", +"2' c #738290", +"3' c #738391", +"4' c #738191", +"5' c #73828F", +"6' c #73838E", +"7' c #73828E", +"8' c #73818E", +"9' c #738193", +"0' c #738091", +"a' c #737F8D", +"b' c #737F8B", +"c' c #74808C", +"d' c #74808E", +"e' c #768093", +"f' c #767F94", +"g' c #757E92", +"h' c #757E94", +"i' c #757F94", +"j' c #768292", +"k' c #768290", +"l' c #76818B", +"m' c #76828F", +"n' c #768392", +"o' c #768391", +"p' c #738094", +"q' c #73828D", +"r' c #6A7883", +"s' c #606D77", +"t' c #3B4651", +"u' c #36434C", +"v' c #45575D", +"w' c #485A63", +"x' c #465762", +"y' c #42535E", +"z' c #41535C", +"A' c #41565F", +"B' c #41575F", +"C' c #495C64", +"D' c #475962", +"E' c #485A62", +"F' c #496069", +"G' c #455B64", +"H' c #384A53", +"I' c #324249", +"J' c #29373C", +"K' c #344046", +"L' c #3D494F", +"M' c #54646B", +"N' c #607179", +"O' c #6F7D88", +"P' c #72808B", +"Q' c #73818B", +"R' c #73808B", +"S' c #737E8B", +"T' c #73808D", +"U' c #727F8A", +"V' c #707F88", +"W' c #6F7F88", +"X' c #6F808C", +"Y' c #6F818E", +"Z' c #6F8290", +"`' c #6F8190", +" ) c #6F8090", +".) c #717F8E", +"+) c #737F8F", +"@) c #73808C", +"#) c #737F89", +"$) c #737F87", +"%) c #727F87", +"&) c #707F87", +"*) c #6F7F89", +"=) c #6F7F8A", +"-) c #717F8B", +";) c #74818C", +">) c #758091", +",) c #748091", +"') c #737E90", +")) c #717C90", +"!) c #727C90", +"~) c #737D91", +"{) c #737E91", +"]) c #737F92", +"^) c #737F91", +"/) c #727F90", +"() c #727F8F", +"_) c #717F8D", +":) c #738092", +"<) c #6F7E8C", +"[) c #6C7C85", +"}) c #616F77", +"|) c #57646B", +"1) c #35424A", +"2) c #4A6069", +"3) c #43565F", +"4) c #43575F", +"5) c #465D64", +"6) c #435961", +"7) c #50616A", +"8) c #4E616A", +"9) c #4B606A", +"0) c #485D67", +"a) c #3D4F58", +"b) c #35454D", +"c) c #2A373D", +"d) c #2E3A41", +"e) c #323E45", +"f) c #4A5760", +"g) c #57656E", +"h) c #667681", +"i) c #6A7A85", +"j) c #6C7C87", +"k) c #717E89", +"l) c #717D89", +"m) c #717C89", +"n) c #707C89", +"o) c #6E7C88", +"p) c #6E7B87", +"q) c #707C88", +"r) c #6D7C89", +"s) c #6C7C89", +"t) c #6B7C89", +"u) c #6B7C88", +"v) c #6A7C84", +"w) c #697C88", +"x) c #697C89", +"y) c #687C89", +"z) c #6A7B88", +"A) c #6B7B87", +"B) c #6B7B86", +"C) c #6B7C84", +"D) c #6B7C83", +"E) c #6B7C82", +"F) c #6B7B82", +"G) c #6B7A81", +"H) c #6A7B81", +"I) c #687B82", +"J) c #697B82", +"K) c #6C7E82", +"L) c #6E7F82", +"M) c #6E7E83", +"N) c #6A7B83", +"O) c #697A82", +"P) c #6A7A82", +"Q) c #6B7A82", +"R) c #697A84", +"S) c #6A7B86", +"T) c #6E7C89", +"U) c #6F7D87", +"V) c #6D7D86", +"W) c #6A7982", +"X) c #697680", +"Y) c #65747D", +"Z) c #617279", +"`) c #4D5D66", +" ! c #42505A", +".! c #33414A", +"+! c #45555D", +"@! c #4B626A", +"#! c #42535C", +"$! c #475E62", +"%! c #435A5E", +"&! c #495E68", +"*! c #435660", +"=! c #334246", +"-! c #2E3B40", +";! c #2C373D", +">! c #35424B", +",! c #3D4B55", +"'! c #4F5F69", +")! c #56666F", +"!! c #5C6D74", +"~! c #5F6F77", +"{! c #617079", +"]! c #627179", +"^! c #627079", +"/! c #607079", +"(! c #5E7078", +"_! c #5B6E75", +":! c #5A6D74", +"~ c #2F393D", +",~ c #2E393D", +"'~ c #2D383C", +")~ c #2C383B", +"!~ c #2C393C", +"~~ c #2C3739", +"{~ c #2C3639", +"]~ c #2B3639", +"^~ c #2A3639", +"/~ c #293639", +"(~ c #283639", +"_~ c #283637", +":~ c #283635", +"<~ c #283538", +"[~ c #283439", +"}~ c #283437", +"|~ c #283435", +"1~ c #283431", +"2~ c #283331", +"3~ c #283131", +"4~ c #283231", +"5~ c #222D30", +"6~ c #202B2E", +"7~ c #263439", +"8~ c #2D3B40", +"9~ c #334147", +"0~ c #394A4F", +"a~ c #485961", +"b~ c #4A5A63", +"c~ c #4D5F69", +"d~ c #4E606A", +"e~ c #40575F", +"f~ c #405760", +"g~ c #455B63", +"h~ c #465C64", +"i~ c #4E646A", +"j~ c #4A5E66", +"k~ c #48575F", +"l~ c #47545C", +"m~ c #435258", +"n~ c #404F55", +"o~ c #3A474D", +"p~ c #354248", +"q~ c #26353B", +"r~ c #223035", +"s~ c #1D2E30", +"t~ c #1A2C2D", +"u~ c #19292B", +"v~ c #19282A", +"w~ c #192829", +"x~ c #202A2B", +"y~ c #20292B", +"z~ c #1C282A", +"A~ c #19292C", +"B~ c #192A2C", +"C~ c #1B2B2C", +"D~ c #19282C", +"E~ c #18292C", +"F~ c #182A2B", +"G~ c #192929", +"H~ c #18292B", +"I~ c #18282C", +"J~ c #18282B", +"K~ c #18292A", +"L~ c #192A29", +"M~ c #1D2A29", +"N~ c #1C2A29", +"O~ c #1A2A29", +"P~ c #1A292A", +"Q~ c #1B292B", +"R~ c #1B292C", +"S~ c #1D2B2F", +"T~ c #223034", +"U~ c #2C393E", +"V~ c #36454A", +"W~ c #3C4B53", +"X~ c #3E4E58", +"Y~ c #455862", +"Z~ c #4B5D68", +"`~ c #4F616C", +" { c #52646F", +".{ c #546570", +"+{ c #556570", +"@{ c #556871", +"#{ c #536770", +"${ c #4E646E", +"%{ c #4D636D", +"&{ c #4D626D", +"*{ c #4B606B", +"={ c #4B616C", +"-{ c #51676D", +";{ c #51656B", +">{ c #51646A", +",{ c #51646B", +"'{ c #526671", +"){ c #526872", +"!{ c #536972", +"~{ c #506772", +"{{ c #4E6672", +"]{ c #4C6270", +"^{ c #4B606D", +"/{ c #485C65", +"({ c #465961", +"_{ c #43545C", +":{ c #3F5057", +"<{ c #3C4D53", +"[{ c #37474F", +"}{ c #34444C", +"|{ c #2E3F47", +"1{ c #2B3C43", +"2{ c #27373D", +"3{ c #203134", +"4{ c #1C2D2F", +"5{ c #192C2D", +"6{ c #192C2C", +"7{ c #192B2D", +"8{ c #192A2E", +"9{ c #1A2A30", +"0{ c #1A2A31", +"a{ c #1B2A31", +"b{ c #1B2B31", +"c{ c #1B2C31", +"d{ c #192C32", +"e{ c #192B32", +"f{ c #192A32", +"g{ c #192932", +"h{ c #192D30", +"i{ c #192D32", +"j{ c #192D31", +"k{ c #192C31", +"l{ c #1B2D32", +"m{ c #1C2D31", +"n{ c #1D2D30", +"o{ c #1B2D30", +"p{ c #1A2D30", +"q{ c #1D2E32", +"r{ c #223237", +"s{ c #24333A", +"t{ c #28363E", +"u{ c #2C3A43", +"v{ c #35434D", +"w{ c #394851", +"x{ c #51666F", +"y{ c #5F737E", +"z{ c #657682", +"A{ c #6A7985", +"B{ c #6A7B89", +"C{ c #697C8A", +"D{ c #677988", +"E{ c #637784", +"F{ c #5B717D", +"G{ c #5A6E7A", +"H{ c #596C78", +"I{ c #546874", +"J{ c #526772", +"K{ c #516572", +"L{ c #536A74", +"M{ c #546A74", +"N{ c #5A6E77", +"O{ c #5D6F79", +"P{ c #5F727F", +"Q{ c #5F7280", +"R{ c #5F7380", +"S{ c #5C7280", +"T{ c #5A7280", +"U{ c #586F7D", +"V{ c #576D7B", +"W{ c #566B75", +"X{ c #546872", +"Y{ c #51636D", +"Z{ c #4C5E67", +"`{ c #394952", +" ] c #304149", +".] c #2C3D44", +"+] c #293A3F", +"@] c #28393D", +"#] c #253638", +"$] c #253536", +"%] c #253537", +"&] c #253539", +"*] c #25353B", +"=] c #25373E", +"-] c #25373C", +";] c #25373B", +">] c #25393D", +",] c #25393E", +"'] c #25383E", +")] c #253940", +"!] c #253941", +"~] c #253B43", +"{] c #263B43", +"]] c #283B43", +"^] c #293B43", +"/] c #2A3B43", +"(] c #2A3C43", +"_] c #2A3D43", +":] c #2B3D43", +"<] c #2C3D43", +"[] c #2F3F47", +"}] c #32414B", +"|] c #33434C", +"1] c #34454D", +"2] c #485862", +"3] c #50636B", +"4] c #536771", +"5] c #556A74", +"6] c #5A6E79", +"7] c #5B6F7B", +"8] c #5B6F7C", +"9] c #5C717D", +"0] c #5D727E", +"a] c #5D737F", +"b] c #5D7380", +"c] c #5C727F", +"d] c #5B6F7E", +"e] c #5C707D", +"f] c #596C7A", +"g] c #576978", +"h] c #536674", +"i] c #526573", +". + @ # $ % & * = - ; > > > > > , ' ) ! > ~ ~ { ] ^ / ( _ : < [ [ [ [ } | [ [ 1 1 1 2 2 3 4 5 6 7 8 9 0 a b 6 5 c d c c e f 5 g h i j 5 5 5 5 5 5 5 6 k l j m m m m m m m m n n n n n n n o p q q q q q q r s t u v w w x y y y y y y z A B C D E F F G H I J K L M M ", +"N O P Q R S T U U V V W X X Y Z ` ...+.@.#.$.#.%.&.*.=.-.;.;.>.,.,.'.).!.~.~.~.{.;.~.].^./.(.(.(._.:.<.[.>.>.-.}.(.|.|.1.2.3.4.4.5.6.7.8.9.0.(./.<.a.b.c.d.>.~.~.>.>.e.-.f.g.g.h.h.h.h.h.i.j.k.k.l.l.l.m.n.o.p.p.q.r.s.t.u.~.v.w. .x.Z B y.y.B Z z.z.A.B.H Y C.D.E.E.", +"F.G.H.I.J.C K.L.M.N.O.B.P.Q.R.S.T.U.V.V.k.W.X.g.g.Y.Y.Z.X.X.X.X.`.1. +.+X.++++@+3.X.#+#+$+$+%+%+&+*+=+-+-+|.;+>+>+>+,+'+)+!+~+~+~+{+]+^+/+(+_+_+:+:+:+<+[+}+|+1+1+|+2+3+4+5+6+7+8+8+9+0+0+a+b+c+d+e+f+g+h+i+j+k+l+m+n+m+o+p+q+r+V.s+t+u+v+w+x+y+z+A+B+C+C.D+E+F+G+H+H+", +"I+J+K+L+M+C.N+O+P+Q+R+S+F T+U+V+W+X+Y+Z+`+ @.@+@.@@@@@#@$@$@$@#@%@%@&@*@=@=@=@-@;@>@,@,@'@'@)@!@>@~@{@]@^@/@/@(@_@:@<@[@}@}@|@|@|@1@1@2@3@4@5@5@6@6@7@2@8@8@8@9@9@8@8@0@a@a@b@c@d@e@f@g@h@i@j@k@l@m@n@o@p@q@r@s@M t@t@u@v@w@x@y@z@A@B@C@D@E@F@G@H@I@J@K@L@M@N@O@P@Q@Q@", +"R@S@T@U@V@W@X@Y@Z@Z@K `@ #.#+#@###$#%#&#*#=#-#;#>#,#,#'#>#>#'#'#)#)#)#!#~#~#~#~#~#{#]#]#^#/#(#_#:#<#[#}#|#1#2#3#4#5#6#7#8#9#2#3#0#3#3#a#b#c#d#e#f#f#g#g#f#h#i#j#j#k#l#m#n#o#p#p#p#p#q#r#r#s#t#u#v#w#x#y#z#A#B#C#t#p#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#X@W#X#Y#Z#Z#", +"`# $.$+$@$#$$$%$&$*$=$-$;$>$,$'$)$!$~${$]$^$/$($($($_$:$<$<$[$}$}$|$1$2$3$4$4$4$4$4$5$5$6$7$8$9$0$a$b$c$d$e$f$g$h$h$e$i$j$k$l$m$_$n$o$p$q$r$s$t$u$v$w$x$y$z$A$B$C$D$E$F$G$H$I$I$I$I$I$I$I$J$K$L$M$o$N$O$P$Q$R$S$T$U$V$W$X$Y$Z$`$ %.%+%@%x@#%$%%%&%*%=%-%;%>%,%'%)%!%!%", +"~%{%]%^%/%(%_%:%:%<%[%}%|%1%2%3%4%5%6%7%8%9%0%a%b%c%c%c%d%d%e%e%e%e%e%f%g%h%h%h%i%j%k%k%l%m%e%n%o%p%q%i%h%r%s%e%e%e%t%t%g%u%v%w%x%y%y%y%x%z%A%B%C%D%x%z%E%F%G%v%v%v%H%I%H%H%v%v%v%v%v%v%v%J%K%q%q%p%L%L%L%M%N%O%y%x%w%P%Q%R%S%o#T%U%V%W%X%Y%Z%`% &.&+&@&#&$&%&&&*&=&=&", +"-&;&>&,&'&)&!&~&~&~&{&&@]&^&/&(&_&:&<&[&}&}&}&|&1&2&3&4&4&4&4&4&4&4&4&5&6&7&7&8&9&6&0&7&7&a&3&3&<&4&4&4&4&3&3&3&<&<&4&4&b&b&c&d&e&e&e&e&e&e&e&e&f&g&h&h&e&e&e&e&e&c&c&i&j&j&k&l&m&n&o&4&4&p&q&r&s&t&u&4&4&v&w&x&x&f&h&e&e&h&y&z&A&B&C&D&E&F&G&H&I&`%J&K&L&M&N&O&P&Q&Q&", +"R&S&T&U&# V&W&X&Y&Z&~&`& *.*+*@*#*$*l&%*e&e&e&e&&***=*6&6&6&6&6&6&6&6&6&6&7&7&0&6&-*;*9&=*=*=*=*>*,*'*)*!*~*{*)*'*>*=*]*^*/*(*k&_*:*_*f&f&f&<*[*}*}*|*1*2*3*4*3*5*6*7*8*9*~*0*a*b*c*}*a#d*e*f*=*;*g*g*g*7&9&h*i*j*6*9#[*:*k*l*m*n*B&o*p*q*r*s*t*t*V&u*v*w*x*y*N&z*Q&Q&", +"R&S&r*A*B*W&C*D*D*Y&E*F*G*H*I*J*K*L*M*N*O*O*O*O*P*j*j*Q*Q*Q*Q*Q*Q*Q*Q*i*R*h*h*R*R*j*i*S*Q*Q*!*9*~*a*T*U*U*U*U*U*V*a*0*0*W*W*0*0*0*X*W*Y*Z*`* =.=+=+=@=Z*#=$=%=V*V*V*V*U*U*U*U*U*U*V*&=+=*=Q*Q*Q*Q*j*}*}*d*d*R*}*}*|*==}*j*Q**=c*-=B&;=p*q*r*>=,='=)=!=~&~={=]=^=z*Q&Q&", +"/=(=_=:=B*<=[=}=|=)=J&1=2=3=4=5=6=7=8=9=}*j*j*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*j*j*j*j*Q*j*j*!*9*W*a*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*a*0*T*T*U*U*U*U*U*U*U*U*U*U*U*U*U*U*T*W*9*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*Q*)*0=a=b=B&;=p*q*r*>=c=c=)=!=d=e=f=g=^=z*Q&Q&", +"h=i=j=k=l=m=n=o=<=p=q=r=s=t=u=v=w=x=y=Q*j*Q*Q*Q*Q*Q*)*z=z=z=A=)*Q*B=C=C=C=C=Q*Q*B=C=D=D=E=F=G=H=I=G=G=G=G=G=G=G=G=G=G=U*U*U*U*U*U*H=G=H=U*U*U*U*G=G=U*U*I=G=G=G=G=G=G=H=U*G=G=G=I=U*T*J=E=C=K=C=C=C=C=C=C=L=M=L=L=)*)*z=z=N=y=O=-=P=Q=R=S=T=U=V=W=[=<=X=Y=Z=`= -.-+-+-", +"@-#-$-k=%-&-*-&-)=u*{&r==---;->-,-'-)-!-Q*Q*Q*Q*Q*)*A=~-~-~-N=N={-]-]-]-]-]-Q*^-/-]-]-]-]-]-]-(-G=]-]-]-]-]-]-]-]-]-]-U*U*U*U*U*U*(-]-]-_-U*:-<-]-]-U*U*G=]-]-]-]-]-]-(-U*H=]-]-]-[-}-|-]-1-L=]-]-]-]-]-]-]-]-]-]-A=)*z=N=N=~*2-3-4-5-6-7-8-9-0-a-m=b-d=Y=Z=c-d-e-e-e-", +"f-g-h-:=%-&-i-&-)=j-k-l-m-n-o-p-q-r-s-t-A=)*Q*Q*)*N=t-}-T*U*T*u-]-]-v-w-L=x-y-z-A-]-]-B-G=G=G=H=I=G=G=G=C-]-]-_-G=G=G=U*U*U*U*U*U*(-]-]-D-E-F-U*]-]-U*U*G=]-]-C-G=G=G=H=U*U*C-]-]-G-H-D-D-!-I-D=E=J-B-]-]-x-K-L-L-~-~-M-M-t-~*Y*N-O-P-Q-R-S-~&T-a-U-V-~&e=Z=c-W-e-e-e-", +"@-#-$-k=%-W&C*W&)=u*{&r==---X-Y-Z-`- ;.;N=z=A=z=z=N=t-}-T*U*U*(-]-]-G-t-N=+;T*U*G=]-]-(-U*U*U*U*U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-]-]-]-U*U*]-]-U*U*G=]-]-(-U*U*U*U*U*U*@;]-]-]-C-]-#;0*0*T*T*U*(-]-]-$;%;&;+;t-t-T*U*U*2-*;=;-;5-;;R-S-~&T->;<=,;~&e=Z=c-W-';';';", +"@-#-$-k=l=);!;~;{;];F&^;/;t=(;_;:;<;[;};N=N=N=~-~-~-|;T*U*U*U*1;]-]-]-D-L-M-}-U*G=]-]-C-G=G=G=U*U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-]-]-]-_-U*]-]-U*U*G=]-]-C-G=G=G=U*U*U*V*G-]-]-]-_-2;2;2;U*U*U*(-]-]-3;4;[;+;M-M-T*U*U*5;[#6;7;8;9;0;S-~&!=a;!=!=p=b;c;c-*%d;8@8@", +"@-#-$-k=%-&-i-e;{;f;g;h;i;j;k;9@l;m;n;o;+;M-|;T*U*2;2;p;2;2;U*U*_-]-]-]-]-_-U*U*G=]-]-]-]-]-]-U*U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-(-]-]-]-H=]-]-U*U*G=]-]-]-]-]-]-U*U*U*U*U*]-]-]-G=U*U*U*U*U*U*(-]-]-G=q;r;U*U*U*U*U*U*U*U*s;t;u;v;w;S-~&x;y;z;x;Z% &A;B;C;D;E;E;", +"@-#-$-k=%-&-i-e;{;p={&F;G;j;k;9@H;I;J;K;2;U*U*U*U*U*2;%;%;%;2;U*U*G=C-]-]-]-C-U*G=]-]-C-G=G=G=U*U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-G=1;]-]-D-]-]-U*U*G=]-]-C-G=G=G=U*U*U*U*I=]-]-]-C-I=U*U*U*U*U*(-]-]-G=q;r;U*U*U*U*U*U*U*U*s;t;L;M;N;O;~&t*z;P;t*Z% &A;B;C;D;E;E;", +"Q;R;S;T;U;&-i-e;{;!=q=F;G;j;k;9@V;W;X;Y;p;2;U*U*U*U*2;Z;`;`;%;p;U*U*I=_-]-]-]-U*G=]-]-(-U*U*U*U*U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-G=I=D-]-]-]-]-U*U*G=]-]-(-U*U*U*U*U*U*U*_-]-]-]-]-1;U*U*U*U*U*(-]-]-G=q;r;U*U*U*U*U*U*2;2; >.>^=+>@>O;~&#>s*c=t*Z% &A;B;C;D;E;E;", +"$>%>b;&>!=<=*>e;{;a;=>F;G;j;k;->;>>>,>'>2;U*U*U*2;Z;)>!>~>{>]>`;p;2;U*U*]-]-]-U*G=]-]-(-U*U*U*U*U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-G=U*H=]-]-]-]-U*U*G=]-]-(-U*U*U*U*U*U*G=]-_-G=]-]-]-U*U*U*U*U*(-]-]-G=q;r;U*U*U*U*U*U*2;p; >.>^>Z#@>O;~&/>I&c=t*Z% &A;B;C;D;E;E;", +"$>(>_>:>T-<>[>[>[>,;}>|>1>2>3>4>5>6>7>8>U*U*U*2;K;9>0>q;a>a>K;b>C-b>(-C-]-]-1;U*G=]-]-D-(-(-(-(-U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-G=U*U*1;]-]-]-U*U*G=]-]-D-(-(-(-(-U*U*D-D-c>8>C-]-]-d>8>U*e>r;f>]-]-g>h>i>j>a>a>j>k>U*l>m>n>o>p>q>r>s>t>Z%,;I&Z%V&b;c;c-u>v>v>v>", +"f-w>$-k=x>y>[>*>i-V&z>A>B>C>D>E>F>G>,>Y;a>r;U*U*U*e>e>U*U*U*U*(-]-]-]-]-C-1;U*U*G=]-]-]-]-]-]-]-U*U*U*U*(-]-]-G=U*U*U*U*U*U*U*U*U*(-]-G=U*U*U*C-]-]-U*U*G=]-]-]-]-]-]-]-U*_-]-d>H>a>I>]-]-]-J>U*k>K>L>]-]-M>N>O>O>O>O>$*P>Q>R>S>T>U>V>W>X>Y>P;U;a;X=X=d=Y=Z=c-W-';';';", +"f-g-$-k=x>y>[>*>i-,;Z>`> ,.,+,@,F>m;n;K;8>U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*8>8>r;H>K>0>#,#,#,9>9>K>0>#,#,#,#,#,#,O>N>i>$,Q>z-$*%,&,*,=,-,W>X>;,y;>,}=!=X=d=Y=Z=c-W-';';';", +",,',$-k=x>y>[>*>i-,;Z>),!,~,{,9@],^,/,2;U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*U*8>8>8>8>8>8>8>8>8>8>8>8>U*U*U*U*U*U*U*U*U*U*U*U*U*8>r;r;(,0>#,#,#,#,#,#,#,#,#,#,#,#,q;q;K>_,N>P>:,z-:,$*<,[,},|,1,2,3,4,5,&-[=!=X=d=Y=Z=c-W-';';';", +"6,7,8,k=x>y>[>*>i-,;S;9,0,~,{,9@],^,J;'>H>r;e>U*U*U*U*U*U*U*r;H>r;8>U*U*U*U*U*U*U*U*U*U*U*e>H>H>a>(,(,a,a,b,l>8>U*U*r;r;H>H>H>r;r;H>H>H>H>r;8>8>8>8>8>8>8>8>8>8>8>8>r;H>(,K>#,#,#,#,#,#,#,#,#,#,#,#,K>a>e>e>:,_,O>#,#,N>P>U*c,d,e,f,g,h,i,j,k,H&|=p=d=d=Y=Z=c-W-';';';", +"l,m,n,o,<=[=[>}=p,U;:=q,r,s,Q-t,u,v,w,x,y,z,A,2;U*U*2;%;%;%;]>{>Z;Z;p;A,/,n;n;A,A,p;2;2;B,b,C,D,D,D,D,E,E,F,F,G,H,H,H,H,I,I,N>O>O>#,#,#,#,O>K>(,a>a>x,J,K,L,M,M,M,J;J;J;N,N,{>{>{>{>{>{>{>O,P,Q,O,{>R,S,T,U,V,W,X,Y,Y,Y,Y,Z,N-`, '.'$$+'@'#'!=$'%'G&U;d=b;&'*'='-';';'", +">','''d=<=}=*>}=<>a;)'!'~'`@{']'^'/'('_':'Y;Y;8>U*r;H>:':':'Y;<'U*U*U*['}'|'|'K,1':'!>!>D,D,2'2'3'3'3'|'|'4'4'4'4'4'4'4'5'5'6'6'6'7'7'8'|'9'#,#,#,9'0'0'}'a'b'b'b'b'b'b'c'd'e'P,f'f'f'f'f'g'g'h'i':'(,q;j'k'l'm'n'o'o'J,!>p'|'q'r's't'u'@'v'd=}=[>5,H&V&w'x'y'z'A'B'B'", +"C'D'E':>U;W&D*C**-F'G'H'I'J'K'L'M'N'O'P'Q'Q'Q'Q'Q'Q'R'S'b'R'Q'Q'6;8'|'T'b'b'b'b'b'b'U'U'V'W'X'Y'Z'`' ).).)}'}'}'}'}'}'+)T'@)b'b'b'#)#)$)%)&)*)=)-)-)b'b'b'R'Q'Q'Q'Q'Q'Q';) >>),)}'}'}'')')))!)~){)])^)}'/)()_)()}'}'}'')^):)<)[)})|)+$1)i,Y%X=}=[>2)5,Z%w'x'y'z'3)4)4)", +"5)6) &&>)=o=7)8)D*9)0)a)b)c)d)e)f)g)h)i)j)O'k)l)m)m)m)m)m)m)n)n)o)o)p)q)m)m)n)r)s)t)u)u)v)v)w)x)y)y)y)z)z)A)A)A)A)A)A)B)C)D)E)F)F)G)G)G)G)H)H)H)I)I)J)J)J)K)L)L)L)L)L)L)M)M)C)N)O)P)Q)Q)Q)R)S)s)T)m)U)V)N)J)P)Q)Q)F)F)W)O-X)Y)Z)`) !.!Q@+!E'G&*>@!D*X&Z%w'&'*'#!w*Z=Z=", +"$!%!''X=<=~;7)8)D*9)&!*!y*=!-!;!>!,!'!)!!!~!{!]!]!{!{!^!^!^!/!(!_!:!C!D!Q@E!F!# t>z;G!*-8)X&U;E'Z=#!#!H!I!I!", +"B*J!T;p=~;K!L!M!N!@!O!!&P!Q!R!S!T!U!V!W!X!Y!Z!`! ~.~+~@~#~#~$~%~&~&~*~=~]&-~=~;~>~,~'~)~s,!~~~~~{~]~^~^~^~~~~~~~~~~~~~~~^~/~(~(~(~(~(~(~_~:~:~:~:~:~:~:~:~<~[~[~[~[~[~[~[~[~[~[~[~[~[~[~[~}~|~1~1~1~2~2~3~3~4~4~4~e+5~6~6+7~8~9~0~7-w*a~b~t>x;c~d~%'~;,;9-j=e~f~g~h~h~", +"%')=!=!=%'i~L!M!N!>,j~E'k~l~m~n~o~p~J q~r~s~t~u~v~w~k.2.x~y~z~V.w~w~w~u~A~B~B~C~C~^.[.[.A~D~D~D~D~E~E~F~F~G~G~G~G~G~G~G~H~H~I~I~I~I~I~I~J~K~L~L~L~L~L~L~L~u~D~D~D~D~D~D~D~D~D~D~D~D~D~D~D~n.l.M~N~O~L~L~w~w~w~P~m.Q~R~S~T~U~G+V~W~X~;'Y~Z~`~ {.{+{@{#{${%{&{*{y;={={={", +"-{;{>{,{'{){!{~{{{]{^{/{({_{:{<{[{}{|{1{2{C.3{G 4{5{t~^.).).-.-.!.!.6{7{8{9{0{a{a{a{b{c{d{d{d{e{f{g{g{e{e{h{h{h{h{h{h{h{i{i{d{d{d{d{d{d{d{j{h{h{h{h{h{h{h{k{d{d{d{d{d{d{d{d{d{d{d{d{d{d{d{l{m{8+n{o{p{h{h{h{#.q{L+r{s{t{u{v{w{S=*'s>x;x{y{z{A{B{C{D{E{F{G{H{I{J{K{K{K{", +"L{M{N{O{P{Q{R{S{T{U{V{W{X{Y{Z{# c-]=`{Y# ].]f +]@]y #]$]$]$]%]&]*]s =]-]y y y y y y ;];]>],],]']=]=]=])]!]~]~]~]~]~]~]{]]]^]/]/]/]/]/]/](]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]_]:]<][]}]|]1]`{;&2]Z{3]4]5]6]7]8]9]0]a]b]a]c]d]e]9]f]g]h]i]i]"}; diff --git a/gtk2_ardour/pixmaps/small-round-button-01.xpm b/gtk2_ardour/pixmaps/small-round-button-01.xpm new file mode 100644 index 0000000000..871f90ce55 --- /dev/null +++ b/gtk2_ardour/pixmaps/small-round-button-01.xpm @@ -0,0 +1,598 @@ +/* XPM */ +static char * t_small_round_button_01_xpm[] = { +"28 30 565 2", +" c None", +". c #3C4B52", +"+ c #465960", +"@ c #44575D", +"# c #45565D", +"$ c #4A5961", +"% c #3A4B53", +"& c #39464D", +"* c #32424A", +"= c #34464D", +"- c #36454C", +"; c #34434C", +"> c #35464E", +", c #34444C", +"' c #34434D", +") c #35454F", +"! c #374750", +"~ c #314248", +"{ c #34444A", +"] c #2A343A", +"^ c #3A454C", +"/ c #37464F", +"( c #394850", +"_ c #3E4F55", +": c #405157", +"< c #3E5259", +"[ c #46585F", +"} c #41545A", +"| c #3E5057", +"1 c #3E4E57", +"2 c #3E4C56", +"3 c #39494F", +"4 c #36434A", +"5 c #273437", +"6 c #2F3A41", +"7 c #394952", +"8 c #3A4E58", +"9 c #40525C", +"0 c #41515A", +"a c #45555B", +"b c #42565B", +"c c #41555A", +"d c #45575E", +"e c #43575C", +"f c #45545E", +"g c #45525A", +"h c #42525A", +"i c #415158", +"j c #3D4E56", +"k c #3C4D55", +"l c #354750", +"m c #2D3B45", +"n c #2E3B43", +"o c #404F58", +"p c #42545D", +"q c #43595D", +"r c #42585B", +"s c #45545B", +"t c #414E54", +"u c #35454E", +"v c #2E3E44", +"w c #2A3C42", +"x c #2F4048", +"y c #324249", +"z c #39454B", +"A c #404D51", +"B c #425257", +"C c #43565B", +"D c #41555B", +"E c #41505A", +"F c #394955", +"G c #2D3943", +"H c #324147", +"I c #405259", +"J c #47565F", +"K c #46585C", +"L c #475A5A", +"M c #3B4D4F", +"N c #2C3B3D", +"O c #293B3E", +"P c #33434A", +"Q c #394A52", +"R c #44525B", +"S c #49565D", +"T c #364649", +"U c #2C3D41", +"V c #2D3E41", +"W c #394B4F", +"X c #425659", +"Y c #465561", +"Z c #44545F", +"` c #40515C", +" . c #303D45", +".. c #232F33", +"+. c #43535B", +"@. c #4A5C62", +"#. c #4A5B62", +"$. c #485458", +"%. c #354144", +"&. c #223034", +"*. c #31404A", +"=. c #506069", +"-. c #617380", +";. c #738492", +">. c #7F8E9C", +",. c #7D8C9C", +"'. c #7E8D9C", +"). c #71828E", +"!. c #5D6F79", +"~. c #44555B", +"{. c #2B3C41", +"]. c #344548", +"^. c #43515C", +"/. c #4A5660", +"(. c #43555C", +"_. c #415058", +":. c #263035", +"<. c #40535A", +"[. c #4A5A62", +"}. c #46555E", +"|. c #2D393F", +"1. c #414F5A", +"2. c #687686", +"3. c #8293A5", +"4. c #93A5BC", +"5. c #9DB1C8", +"6. c #9CB1C8", +"7. c #96ABC2", +"8. c #95ABC3", +"9. c #98A9C0", +"0. c #93A5BA", +"a. c #818E9F", +"b. c #576570", +"c. c #35424A", +"d. c #314144", +"e. c #42535A", +"f. c #4A5A61", +"g. c #495A5F", +"h. c #405158", +"i. c #303D42", +"j. c #485A68", +"k. c #4A5B5F", +"l. c #4B5B5D", +"m. c #334345", +"n. c #233037", +"o. c #485660", +"p. c #6C7B8A", +"q. c #8A9AB1", +"r. c #92A1BB", +"s. c #91A3BB", +"t. c #8EA0B6", +"u. c #8799B2", +"v. c #8597B0", +"w. c #8598B0", +"x. c #8C9BB1", +"y. c #90A0B7", +"z. c #95A4B9", +"A. c #8090A4", +"B. c #5D6C7C", +"C. c #2D3F3E", +"D. c #35444C", +"E. c #4A5860", +"F. c #4E5D63", +"G. c #475A61", +"H. c #2C3A3D", +"I. c #3C4C52", +"J. c #4F6271", +"K. c #4A5E61", +"L. c #415051", +"M. c #263437", +"N. c #334149", +"O. c #687583", +"P. c #7F90A1", +"Q. c #899AAF", +"R. c #8393AC", +"S. c #8594AA", +"T. c #8393A7", +"U. c #8391A7", +"V. c #8394AA", +"W. c #8393A8", +"X. c #8696AC", +"Y. c #8496AB", +"Z. c #7A8DA0", +"`. c #526264", +" + c #2A3A3F", +".+ c #424E53", +"++ c #4F5D63", +"@+ c #4D5E62", +"#+ c #3A4B4D", +"$+ c #4D5F66", +"%+ c #4A616A", +"&+ c #485D5D", +"*+ c #2E3F3E", +"=+ c #253238", +"-+ c #7C8A9B", +";+ c #8191A2", +">+ c #8190A4", +",+ c #8091A5", +"'+ c #7E8EA3", +")+ c #7B8DA2", +"!+ c #7C8DA4", +"~+ c #808DA4", +"{+ c #808FA4", +"]+ c #828EA4", +"^+ c #8390A4", +"/+ c #8392A8", +"(+ c #8392A6", +"_+ c #76858D", +":+ c #404E51", +"<+ c #314245", +"[+ c #48595F", +"}+ c #505F6A", +"|+ c #4A5E64", +"1+ c #2D363A", +"2+ c #52626A", +"3+ c #50646A", +"4+ c #435656", +"5+ c #253736", +"6+ c #364148", +"7+ c #6D7A8A", +"8+ c #7C8B9D", +"9+ c #7B8B9E", +"0+ c #7C8EA2", +"a+ c #7C8D9D", +"b+ c #7B8B9C", +"c+ c #7B8C9D", +"d+ c #7B8B9D", +"e+ c #808EA3", +"f+ c #7B8AA1", +"g+ c #7C8BA3", +"h+ c #808EA4", +"i+ c #818D9E", +"j+ c #556668", +"k+ c #2B3E3B", +"l+ c #45565A", +"m+ c #52616A", +"n+ c #4C6065", +"o+ c #283336", +"p+ c #52636A", +"q+ c #52656A", +"r+ c #3A504F", +"s+ c #253437", +"t+ c #48545E", +"u+ c #798496", +"v+ c #7B899D", +"w+ c #7B899E", +"x+ c #7B8A9C", +"y+ c #7A8C9B", +"z+ c #7A899B", +"A+ c #7B899C", +"B+ c #7E8BA3", +"C+ c #808BA3", +"D+ c #7D8AA2", +"E+ c #7E8A9F", +"F+ c #7E8AA2", +"G+ c #7C889D", +"H+ c #6C7B7D", +"I+ c #32443E", +"J+ c #3A4C4F", +"K+ c #4D626A", +"L+ c #4C6068", +"M+ c #4F636A", +"N+ c #50656B", +"O+ c #52666B", +"P+ c #3B4B4A", +"Q+ c #263536", +"R+ c #516067", +"S+ c #778698", +"T+ c #7B889C", +"U+ c #7B8898", +"V+ c #73828B", +"W+ c #394A4F", +"X+ c #374A4F", +"Y+ c #50656A", +"Z+ c #4C6365", +"`+ c #374844", +" @ c #263537", +".@ c #52636E", +"+@ c #768596", +"@@ c #7B8595", +"#@ c #7B859A", +"$@ c #7A879A", +"%@ c #79889C", +"&@ c #7A889C", +"*@ c #79879C", +"=@ c #75859A", +"-@ c #7A8594", +";@ c #75838C", +">@ c #3E4E51", +",@ c #3A4A4F", +"'@ c #51646A", +")@ c #4C626A", +"!@ c #4F6468", +"~@ c #3B4A48", +"{@ c #253536", +"]@ c #52626D", +"^@ c #768398", +"/@ c #768294", +"(@ c #7A8294", +"_@ c #7B8294", +":@ c #7B8494", +"<@ c #7B8696", +"[@ c #7B8698", +"}@ c #7B869C", +"|@ c #78859B", +"1@ c #7A859C", +"2@ c #79859A", +"3@ c #74838B", +"4@ c #3E4F51", +"5@ c #3B4C4F", +"6@ c #52676A", +"7@ c #52666A", +"8@ c #3F4F4E", +"9@ c #253436", +"0@ c #495863", +"a@ c #728091", +"b@ c #778194", +"c@ c #7B8194", +"d@ c #7B8594", +"e@ c #7B8596", +"f@ c #7B859C", +"g@ c #7A859B", +"h@ c #788496", +"i@ c #7B8499", +"j@ c #798596", +"k@ c #6B7B84", +"l@ c #39484B", +"m@ c #3F5052", +"n@ c #52666D", +"o@ c #52686D", +"p@ c #54666D", +"q@ c #435451", +"r@ c #263736", +"s@ c #394950", +"t@ c #70798A", +"u@ c #788092", +"v@ c #788194", +"w@ c #7B8396", +"x@ c #7B8598", +"y@ c #7B8599", +"z@ c #7B849A", +"A@ c #7A8399", +"B@ c #7B8498", +"C@ c #758194", +"D@ c #758393", +"E@ c #5E7076", +"F@ c #334448", +"G@ c #52656D", +"H@ c #52676D", +"I@ c #526973", +"J@ c #536973", +"K@ c #475C5B", +"L@ c #304340", +"M@ c #2D3B41", +"N@ c #626D7C", +"O@ c #717D8D", +"P@ c #738194", +"Q@ c #7A849A", +"R@ c #7A8396", +"S@ c #7B8394", +"T@ c #7B859B", +"U@ c #798194", +"V@ c #7A8497", +"W@ c #778191", +"X@ c #737F88", +"Y@ c #4C5A5D", +"Z@ c #304346", +"`@ c #4B5A62", +" # c #526673", +".# c #526972", +"+# c #2D393A", +"@# c #526A73", +"## c #4F6265", +"$# c #3B4C4D", +"%# c #2A383B", +"&# c #6B7787", +"*# c #737F8F", +"=# c #737F91", +"-# c #7A8394", +";# c #788497", +"># c #7A8495", +",# c #738191", +"'# c #75818F", +")# c #707D88", +"!# c #697579", +"~# c #394947", +"{# c #374B4A", +"]# c #4F6165", +"^# c #526670", +"/# c #43585D", +"(# c #536D73", +"_# c #526771", +":# c #485861", +"<# c #324142", +"[# c #334043", +"}# c #525F6A", +"|# c #6B7A84", +"1# c #737D8B", +"2# c #737F90", +"3# c #738090", +"4# c #738190", +"5# c #768390", +"6# c #788390", +"7# c #73808B", +"8# c #707E8A", +"9# c #657580", +"0# c #48575E", +"a# c #374647", +"b# c #4B5D5C", +"c# c #57696F", +"d# c #576975", +"e# c #44565D", +"f# c #37474E", +"g# c #536D7A", +"h# c #52697A", +"i# c #4F636F", +"j# c #425351", +"k# c #2F3E3C", +"l# c #344148", +"m# c #505E69", +"n# c #69747F", +"o# c #6B7784", +"p# c #6F7C88", +"q# c #717D89", +"r# c #717D8B", +"s# c #6C7D86", +"t# c #6C7D89", +"u# c #6B7C83", +"v# c #485961", +"w# c #334150", +"x# c #435258", +"y# c #54646A", +"z# c #596D78", +"A# c #5A6B7A", +"B# c #39474E", +"C# c #526B78", +"D# c #546C79", +"E# c #576B72", +"F# c #4D6062", +"G# c #384C4D", +"H# c #29383F", +"I# c #2E3C46", +"J# c #4C5960", +"K# c #636D73", +"L# c #65757D", +"M# c #677882", +"N# c #657982", +"O# c #687985", +"P# c #677983", +"Q# c #69777D", +"R# c #68757B", +"S# c #59686D", +"T# c #3C4E54", +"U# c #324348", +"V# c #3A4C59", +"W# c #52636F", +"X# c #5A707D", +"Y# c #586B78", +"Z# c #35434C", +"`# c #586E7B", +" $ c #5A707A", +".$ c #576A71", +"+$ c #4E5F65", +"@$ c #3E4C51", +"#$ c #2E3C40", +"$$ c #293637", +"%$ c #334041", +"&$ c #435156", +"*$ c #505E65", +"=$ c #56666B", +"-$ c #576A6E", +";$ c #556567", +">$ c #4F5B5F", +",$ c #3C4A4D", +"'$ c #2D3C44", +")$ c #314149", +"!$ c #3E515A", +"~$ c #4E626C", +"{$ c #5B6F78", +"]$ c #5D737B", +"^$ c #5A727B", +"/$ c #38464C", +"($ c #4C5E66", +"_$ c #5D727C", +":$ c #5E717D", +"<$ c #596D75", +"[$ c #516569", +"}$ c #455858", +"|$ c #334343", +"1$ c #273636", +"2$ c #233132", +"3$ c #273334", +"4$ c #2B3536", +"5$ c #273536", +"6$ c #273333", +"7$ c #273439", +"8$ c #29373D", +"9$ c #384550", +"0$ c #495B66", +"a$ c #576A73", +"b$ c #5C717C", +"c$ c #61737D", +"d$ c #61757D", +"e$ c #4B5F66", +"f$ c #4F5C68", +"g$ c #627183", +"h$ c #61727F", +"i$ c #5E7178", +"j$ c #556970", +"k$ c #506266", +"l$ c #45585B", +"m$ c #3D4E50", +"n$ c #384648", +"o$ c #364246", +"p$ c #344347", +"q$ c #3B484A", +"r$ c #45555D", +"s$ c #51616A", +"t$ c #586976", +"u$ c #5F7280", +"v$ c #617582", +"w$ c #637884", +"x$ c #4F5F6A", +"y$ c #4F5E6D", +"z$ c #627787", +"A$ c #637A87", +"B$ c #617785", +"C$ c #627683", +"D$ c #64747F", +"E$ c #5E7078", +"F$ c #5C6D73", +"G$ c #5F7077", +"H$ c #5F7178", +"I$ c #62747B", +"J$ c #677784", +"K$ c #6A7B87", +"L$ c #687B87", +"M$ c #6A7E8E", +"N$ c #677B8B", +"O$ c #6A798B", +"P$ c #52606C", +"Q$ c #3D4D52", +"R$ c #5E7383", +"S$ c #687A8B", +"T$ c #6A7D8B", +"U$ c #6A7C8B", +"V$ c #677A8A", +"W$ c #6A7A8A", +"X$ c #6A7B8B", +"Y$ c #6A7C8E", +"Z$ c #6A808E", +"`$ c #6A7F8B", +" % c #6A7E8C", +".% c #6A7E8B", +"+% c #637683", +"@% c #404E55", +"#% c #566672", +"$% c #60717E", +"%% c #6A7D8C", +"&% c #6A8092", +"*% c #6A8190", +"=% c #6E8191", +"-% c #637584", +";% c #576873", +">% c #566671", +" . + @ # $ % ", +" & * = - ; > , ' ) ! ~ { ", +" ] ^ / ( _ : < [ } | 1 2 3 / 4 5 ", +" 6 7 8 9 0 a b c d e f g h i j k l m ", +" n o p q r s t u v w x y z A B C D E F G ", +" H I J K L M N O P Q R S g T U V W X Y Z ` . ", +" ..+.@.#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].^./.(._.:. ", +" <.#.[.}.n |.1.2.3.4.5.6.7.8.9.0.a.b.c.d.e.f.g.h. ", +" i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.D.E.F.G.H. ", +" I.J.K.L.M.N.O.P.Q.R.S.T.U.U.V.W.T.X.Y.Z.`. +.+++@+#+ ", +" $+%+&+*+=+b.-+;+>+,+'+)+!+~+{+]+{+^+/+(+_+:+<+[+}+|+ ", +"1+2+3+4+5+6+7+8+9+0+a+b+c+c+c+d+e+f+g+^+h+i+j+k+l+m+n+o+", +"p+p+q+r+s+t+u+v+w+x+y+z+A+A+A+A+B+C+D+E+F+G+H+I+J+m+K+L+", +"M+N+O+P+Q+R+S+A+A+A+A+A+A+A+A+A+A+A+A+x+T+U+V+W+X+2+3+%+", +"q+Y+Z+`+ @.@+@@@@@#@#@$@A+A+A+A+A+%@&@*@=@-@;@>@,@2+'@)@", +"q+Y+!@~@{@]@^@/@(@_@:@-@<@[@}@}@}@|@1@1@2@-@3@4@5@2+q+q+", +"q+6@7@8@9@0@a@b@b@c@c@:@d@e@f@f@g@h@f@f@i@j@k@l@m@2+q+7@", +"n@o@p@q@r@s@t@u@v@c@w@@@d@x@y@y@f@z@A@B@C@D@E@F@l+G@n@H@", +"|.I@J@K@L@M@N@O@P@b@Q@R@(@S@:@d@T@i@U@V@W@X@Y@Z@`@ #.#+#", +" @#I@##$#%#/.&#*#=#U@C@C@-#:@d@;#>#,#'#)#!#~#{#]#^#I@ ", +" /#(#_#:#<#[#}#|#1#2#3#4#4#5#6#3#4#7#8#9#0#a#b#c#d#e# ", +" f#g#h#i#j#k#l#m#n#o#p#q#r#r#r#s#t#u#E@v#w#x#y#z#A#B# ", +" C#D#E#F#G#H#I#J#K#L#M#N#O#P#Q#R#S#T#U#V#W#z#X#Y# ", +" Z#`# $.$+$@$#$$$%$&$*$=$-$;$>$,$'$)$!$~${$]$^$/$ ", +" ($_$:$<$[$}$|$1$2$3$4$5$6$7$8$9$0$a$b$c$d$e$ ", +" f$g$h$i$j$k$l$m$n$o$p$q$r$s$t$u$v$w$w$x$ ", +" y$z$A$B$C$D$E$F$G$H$I$J$K$L$M$N$O$P$ ", +" Q$R$S$T$U$V$W$W$X$Y$Z$`$ %.%+%@% ", +" #%$%T$T$T$T$%%&%*%=%-%;% ", +" >%T$T$T$T$>% "}; diff --git a/gtk2_ardour/pixmaps/toggle-button-00.xpm b/gtk2_ardour/pixmaps/toggle-button-00.xpm new file mode 100644 index 0000000000..7606152f3f --- /dev/null +++ b/gtk2_ardour/pixmaps/toggle-button-00.xpm @@ -0,0 +1,354 @@ +/* XPM */ +static char * toggle_button_00_xpm[] = { +"21 22 329 2", +" c None", +". c #52646A", +"+ c #56686E", +"@ c #506268", +"# c #4C5E66", +"$ c #4E626A", +"% c #52646C", +"& c #52636A", +"* c #52636C", +"= c #52636E", +"- c #50626C", +"; c #4E6166", +"> c #4E5F66", +", c #4C5D66", +"' c #4E5E66", +") c #505F68", +"! c #52656A", +"~ c #52676C", +"{ c #54676C", +"] c #415156", +"^ c #2B3A41", +"/ c #24343D", +"( c #28363D", +"_ c #24363D", +": c #24383D", +"< c #29363D", +"[ c #24363F", +"} c #27363F", +"| c #27343B", +"1 c #2D3944", +"2 c #37464E", +"3 c #485960", +"4 c #42545A", +"5 c #29383F", +"6 c #2F3C46", +"7 c #2F4143", +"8 c #334246", +"9 c #2F3F46", +"0 c #314046", +"a c #354246", +"b c #313F46", +"c c #314048", +"d c #333F48", +"e c #313F48", +"f c #33404A", +"g c #2F3B46", +"h c #2B393F", +"i c #3B4A52", +"j c #394C54", +"k c #394752", +"l c #415058", +"m c #415252", +"n c #29393F", +"o c #28383F", +"p c #28373D", +"q c #2D383D", +"r c #2D373D", +"s c #2D3A3D", +"t c #2D393D", +"u c #2B373F", +"v c #2A373D", +"w c #283837", +"x c #283A3D", +"y c #3B4952", +"z c #3D4D56", +"A c #394750", +"B c #3F5258", +"C c #44565E", +"D c #46585E", +"E c #39474A", +"F c #3B4B56", +"G c #4E5A66", +"H c #525C66", +"I c #525E6A", +"J c #52606A", +"K c #56606A", +"L c #525E68", +"M c #48585E", +"N c #2F3E3D", +"O c #202F31", +"P c #2A3B42", +"Q c #46545E", +"R c #435260", +"S c #3D4D58", +"T c #43575E", +"U c #4A5A62", +"V c #4E5B5E", +"W c #37484E", +"X c #62707F", +"Y c #8190A8", +"Z c #8C9AB4", +"` c #8E9EB4", +" . c #8E9EB8", +".. c #8C9CB4", +"+. c #8C9EB4", +"@. c #90A0B8", +"#. c #90A2B6", +"$. c #90A0B4", +"%. c #90A2B0", +"&. c #627379", +"*. c #2B363D", +"=. c #2D3A46", +"-. c #465766", +";. c #465762", +">. c #3F4F5A", +",. c #465860", +"'. c #4A5D62", +"). c #4E6164", +"!. c #6A7A8E", +"~. c #92A0BE", +"{. c #94A2C0", +"]. c #94A6C4", +"^. c #94A6C9", +"/. c #94A4C3", +"(. c #94A4C0", +"_. c #96A6C2", +":. c #96A4C2", +"<. c #909EB8", +"[. c #8392A0", +"}. c #424C54", +"|. c #2F3F48", +"1. c #4A5B66", +"2. c #4A5962", +"3. c #3F515C", +"4. c #4A5F62", +"5. c #4C5F62", +"6. c #37414A", +"7. c #68748C", +"8. c #7F8EAA", +"9. c #7F8FA8", +"0. c #7F8EA8", +"a. c #7F8DA8", +"b. c #7F8BA6", +"c. c #7D88A2", +"d. c #7D8998", +"e. c #46565E", +"f. c #2D4048", +"g. c #3D505A", +"h. c #465B5E", +"i. c #4A5F66", +"j. c #313D4A", +"k. c #667184", +"l. c #7B87A2", +"m. c #7B89A4", +"n. c #7987A2", +"o. c #7785A0", +"p. c #7B879C", +"q. c #7B88A0", +"r. c #7B869E", +"s. c #7B8596", +"t. c #46565A", +"u. c #2D3D42", +"v. c #465B66", +"w. c #4A5E66", +"x. c #313C48", +"y. c #64707F", +"z. c #79859A", +"A. c #798598", +"B. c #738598", +"C. c #738398", +"D. c #73849A", +"E. c #73859C", +"F. c #75859A", +"G. c #778798", +"H. c #77859A", +"I. c #79849C", +"J. c #758490", +"K. c #46585A", +"L. c #2B3C42", +"M. c #465A62", +"N. c #465B62", +"O. c #4A5C66", +"P. c #2F3C43", +"Q. c #606C7D", +"R. c #778294", +"S. c #798394", +"T. c #758394", +"U. c #738394", +"V. c #738294", +"W. c #738194", +"X. c #738494", +"Y. c #738396", +"Z. c #738496", +"`. c #73818B", +" + c #263A40", +".+ c #485B64", +"++ c #4A5C62", +"@+ c #3F505A", +"#+ c #2D3D43", +"$+ c #5E6C78", +"%+ c #778094", +"&+ c #778194", +"*+ c #738192", +"=+ c #737E8B", +"-+ c #283A42", +";+ c #41505A", +">+ c #465A5E", +",+ c #2D3D41", +"'+ c #5E6B76", +")+ c #738190", +"!+ c #737D8B", +"~+ c #465656", +"{+ c #2D3B42", +"]+ c #465A64", +"^+ c #4A5B62", +"/+ c #41515A", +"(+ c #465B64", +"_+ c #4A5D64", +":+ c #2D3D3D", +"<+ c #5C6A74", +"[+ c #737F8B", +"}+ c #73808B", +"|+ c #73808D", +"1+ c #737F90", +"2+ c #737F92", +"3+ c #737F8D", +"4+ c #6E7D87", +"5+ c #445256", +"6+ c #2D3C42", +"7+ c #465962", +"8+ c #41525A", +"9+ c #4A5E62", +"0+ c #46595E", +"a+ c #2B3B41", +"b+ c #5A6A72", +"c+ c #6C7B87", +"d+ c #6E7C89", +"e+ c #6E7B87", +"f+ c #6C7C89", +"g+ c #6A7B89", +"h+ c #6A7987", +"i+ c #6A7B87", +"j+ c #687B87", +"k+ c #6A7A83", +"l+ c #404A4E", +"m+ c #2F3D44", +"n+ c #485A64", +"o+ c #41545A", +"p+ c #2D3D46", +"q+ c #647581", +"r+ c #647783", +"s+ c #627583", +"t+ c #647681", +"u+ c #62757F", +"v+ c #60757F", +"w+ c #64757F", +"x+ c #62737B", +"y+ c #334248", +"z+ c #2F3F44", +"A+ c #4A5D66", +"B+ c #485C66", +"C+ c #2A3D44", +"D+ c #31414A", +"E+ c #526268", +"F+ c #56676E", +"G+ c #56696E", +"H+ c #56656E", +"I+ c #54666E", +"J+ c #56666C", +"K+ c #4E5C64", +"L+ c #374A52", +"M+ c #4C6068", +"N+ c #3F525A", +"O+ c #4A5D6A", +"P+ c #3D5056", +"Q+ c #2F3F41", +"R+ c #273639", +"S+ c #223133", +"T+ c #203033", +"U+ c #203437", +"V+ c #203335", +"W+ c #203235", +"X+ c #223135", +"Y+ c #2D393F", +"Z+ c #394B52", +"`+ c #445862", +" @ c #4C6268", +".@ c #41555A", +"+@ c #465D66", +"@@ c #485D66", +"#@ c #4A5F6A", +"$@ c #3B4D54", +"%@ c #2D3A42", +"&@ c #28373E", +"*@ c #283840", +"=@ c #26363E", +"-@ c #24363E", +";@ c #2B3840", +">@ c #35454E", +",@ c #48575E", +"'@ c #4E606A", +")@ c #4C606A", +"!@ c #465C64", +"~@ c #3D525C", +"{@ c #4A606A", +"]@ c #4A616A", +"^@ c #485B62", +"/@ c #435660", +"(@ c #3D4E56", +"_@ c #3D4C56", +":@ c #4A5B64", +"<@ c #4C5F68", +"[@ c #4A5E68", +"}@ c #485F68", +"|@ c #506773", +"1@ c #526875", +"2@ c #566A77", +"3@ c #566975", +"4@ c #526570", +"5@ c #4E636C", +"6@ c #4A5F68", +"7@ c #546670", +"8@ c #566A72", +"9@ c #566B75", +"0@ c #546973", +"a@ c #50656E", +"b@ c #526971", +"c@ c #526A75", +"d@ c #546C77", +"e@ c #566D7B", +"f@ c #586D7B", +"g@ c #586C79", +"h@ c #546A73", +"i@ c #566B73", +"j@ c #566C77", +"k@ c #566D77", +"l@ c #566B77", +"m@ c #546777", +"n@ c #526673", +". + @ # $ % & * = - ; > , # > > > ' ) ! ~ ", +"{ ] ^ / ( _ : < [ } < < < < < < < | 1 2 3 ", +"4 5 6 7 8 9 0 a b b 0 0 0 c d b e f g h i ", +"j k l m n o ( p q r s s t u v w x y z A k ", +"B C D E F G H H I I J K J L M N O P Q R S ", +"T U V W X Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.", +",.'.).y !.~.{.].^./.(.(._.:.<.[.}.|.1.2.3.", +";.4.5.6.7.8.9.9.9.0.a.a.9.b.c.d.e.f.1.2.g.", +"h.i.'.j.k.l.m.m.m.n.o.p.p.q.r.s.t.u.v.2.g.", +"h.w.1.x.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.U g.", +"N.O.1.P.Q.R.S.T.U.V.W.U.X.Y.Z.`.t. +.+++@+", +"v.1.M.#+$+%+&+W.V.V.W.W.W.W.*+=+t.-+v.++;+", +"v.O.>+,+'+%+&+W.W.W.W.W.W.W.)+!+~+{+]+^+/+", +"(+_+h.:+<+=+[+}+`.|+1+1+1+2+3+4+5+6+7+^+8+", +"N.9+0+a+b+c+d+e+f+g+h+i+i+d+j+k+l+m+n+++o+", +"N.'.o+p+% q+r+s+s+t+u+u+u+v+w+x+y+z+A+++8+", +"N.'.B+C+D+E+F++ G+F+H+H+H+I+J+K+D+L+M+'.N+", +"N.A+O+P+Q+R+S+T+U+V+W+W+W+X+Y+Z+`+w. @'..@", +"+@@@#@T $@y+%@&@*@&@=@-@=@;@>@,@'@)@M+!@~@", +"{@]@]@#@^@/@@+z P+(@z _@z g./@:@<@'@[@}@M.", +"|@1@2@3@4@5@<@i.6@i.i.i.i.<@'@7@8@9@3@0@a@", +"b@c@d@e@f@g@h@h@i@i@i@i@i@i@i@j@k@l@2@m@n@"}; diff --git a/gtk2_ardour/pixmaps/toggle-button-01.xpm b/gtk2_ardour/pixmaps/toggle-button-01.xpm new file mode 100644 index 0000000000..e1050839be --- /dev/null +++ b/gtk2_ardour/pixmaps/toggle-button-01.xpm @@ -0,0 +1,365 @@ +/* XPM */ +static char * toggle_button_01_xpm[] = { +"21 22 340 2", +" c None", +". c #52646A", +"+ c #56686E", +"@ c #506268", +"# c #4C5E66", +"$ c #4E626A", +"% c #52646C", +"& c #52636A", +"* c #52636C", +"= c #52636E", +"- c #50626C", +"; c #4E6166", +"> c #4E5F66", +", c #4C5D66", +"' c #4E5E66", +") c #505F68", +"! c #52656A", +"~ c #52676C", +"{ c #54676C", +"] c #415156", +"^ c #2B3A41", +"/ c #24343D", +"( c #28363D", +"_ c #24363D", +": c #24383D", +"< c #29363D", +"[ c #24363F", +"} c #27363F", +"| c #27343B", +"1 c #2D3944", +"2 c #37464E", +"3 c #485960", +"4 c #42545A", +"5 c #29383F", +"6 c #2F3C46", +"7 c #2F4143", +"8 c #334246", +"9 c #2F3F46", +"0 c #314046", +"a c #354246", +"b c #313F46", +"c c #314048", +"d c #333F48", +"e c #313F48", +"f c #33404A", +"g c #2F3B46", +"h c #2B393F", +"i c #3B4A52", +"j c #394C54", +"k c #394752", +"l c #415058", +"m c #415252", +"n c #29393F", +"o c #28383F", +"p c #28373D", +"q c #2D383D", +"r c #2D373D", +"s c #2D3A3D", +"t c #2D393D", +"u c #2B373F", +"v c #2A373D", +"w c #283837", +"x c #283A3D", +"y c #3B4952", +"z c #3D4D56", +"A c #394750", +"B c #3F5258", +"C c #44565E", +"D c #46585E", +"E c #39474A", +"F c #3B4B56", +"G c #4E5A66", +"H c #525C66", +"I c #525E6A", +"J c #52606A", +"K c #56606A", +"L c #525E68", +"M c #48585E", +"N c #2F3E3D", +"O c #202F31", +"P c #2A3B42", +"Q c #46545E", +"R c #435260", +"S c #3D4D58", +"T c #43575E", +"U c #4A5A62", +"V c #4E5B5E", +"W c #37484E", +"X c #62707F", +"Y c #8190A8", +"Z c #8C9AB4", +"` c #8E9EB4", +" . c #8E9EB8", +".. c #8C9CB4", +"+. c #8C9EB4", +"@. c #90A0B8", +"#. c #90A2B6", +"$. c #90A0B4", +"%. c #90A2B0", +"&. c #627379", +"*. c #2B363D", +"=. c #2D3A46", +"-. c #465766", +";. c #465762", +">. c #3F4F5A", +",. c #465860", +"'. c #4A5D62", +"). c #4E6164", +"!. c #6A7A8E", +"~. c #92A0BE", +"{. c #94A2C0", +"]. c #94A6C4", +"^. c #94A6C9", +"/. c #94A4C3", +"(. c #94A4C0", +"_. c #96A6C2", +":. c #96A4C2", +"<. c #909EB8", +"[. c #8392A0", +"}. c #424C54", +"|. c #2F3F48", +"1. c #4A5B66", +"2. c #4A5962", +"3. c #3F515C", +"4. c #4A5F62", +"5. c #4C5F62", +"6. c #37414A", +"7. c #68748C", +"8. c #7F8EAA", +"9. c #7F8FA8", +"0. c #7F8EA8", +"a. c #7F8DA8", +"b. c #7F8BA6", +"c. c #7D88A2", +"d. c #7D8998", +"e. c #46565E", +"f. c #2D4048", +"g. c #3D505A", +"h. c #465B5E", +"i. c #4A5F66", +"j. c #313D4A", +"k. c #667184", +"l. c #7B87A2", +"m. c #7B89A4", +"n. c #7B88A3", +"o. c #7B86A0", +"p. c #7A85A0", +"q. c #7B879C", +"r. c #7B88A0", +"s. c #7B869E", +"t. c #7B8596", +"u. c #46565A", +"v. c #2D3D42", +"w. c #465B66", +"x. c #4A5E66", +"y. c #313C48", +"z. c #64707F", +"A. c #79859A", +"B. c #798598", +"C. c #748599", +"D. c #A97E7F", +"E. c #E7765A", +"F. c #E67256", +"G. c #A97B7B", +"H. c #788799", +"I. c #77859A", +"J. c #79849C", +"K. c #758490", +"L. c #46585A", +"M. c #2B3C42", +"N. c #465A62", +"O. c #465B62", +"P. c #4A5C66", +"Q. c #2F3C43", +"R. c #606C7D", +"S. c #778294", +"T. c #798394", +"U. c #788498", +"V. c #E66141", +"W. c #E45A38", +"X. c #E46A4C", +"Y. c #768598", +"Z. c #738396", +"`. c #738496", +" + c #73818B", +".+ c #263A40", +"++ c #485B64", +"@+ c #4A5C62", +"#+ c #3F505A", +"$+ c #2D3D43", +"%+ c #5E6C78", +"&+ c #778094", +"*+ c #778194", +"=+ c #768298", +"-+ c #E24E2A", +";+ c #E46547", +">+ c #738194", +",+ c #738192", +"'+ c #737E8B", +")+ c #283A42", +"!+ c #41505A", +"~+ c #465A5E", +"{+ c #2D3D41", +"]+ c #5E6B76", +"^+ c #748195", +"/+ c #A87A7A", +"(+ c #A77675", +"_+ c #738190", +":+ c #737D8B", +"<+ c #465656", +"[+ c #2D3B42", +"}+ c #465A64", +"|+ c #4A5B62", +"1+ c #41515A", +"2+ c #465B64", +"3+ c #4A5D64", +"4+ c #2D3D3D", +"5+ c #5C6A74", +"6+ c #737F8B", +"7+ c #73808B", +"8+ c #74818D", +"9+ c #768293", +"0+ c #768093", +"a+ c #747F90", +"b+ c #737F90", +"c+ c #737F92", +"d+ c #737F8D", +"e+ c #6E7D87", +"f+ c #445256", +"g+ c #2D3C42", +"h+ c #465962", +"i+ c #41525A", +"j+ c #4A5E62", +"k+ c #46595E", +"l+ c #2B3B41", +"m+ c #5A6A72", +"n+ c #6C7B87", +"o+ c #6E7C89", +"p+ c #6E7B87", +"q+ c #6C7C89", +"r+ c #6A7B89", +"s+ c #6A7987", +"t+ c #6A7B87", +"u+ c #687B87", +"v+ c #6A7A83", +"w+ c #404A4E", +"x+ c #2F3D44", +"y+ c #485A64", +"z+ c #41545A", +"A+ c #2D3D46", +"B+ c #647581", +"C+ c #647783", +"D+ c #627583", +"E+ c #647681", +"F+ c #62757F", +"G+ c #60757F", +"H+ c #64757F", +"I+ c #62737B", +"J+ c #334248", +"K+ c #2F3F44", +"L+ c #4A5D66", +"M+ c #485C66", +"N+ c #2A3D44", +"O+ c #31414A", +"P+ c #526268", +"Q+ c #56676E", +"R+ c #56696E", +"S+ c #56656E", +"T+ c #54666E", +"U+ c #56666C", +"V+ c #4E5C64", +"W+ c #374A52", +"X+ c #4C6068", +"Y+ c #3F525A", +"Z+ c #4A5D6A", +"`+ c #3D5056", +" @ c #2F3F41", +".@ c #273639", +"+@ c #223133", +"@@ c #203033", +"#@ c #203437", +"$@ c #203335", +"%@ c #203235", +"&@ c #223135", +"*@ c #2D393F", +"=@ c #394B52", +"-@ c #445862", +";@ c #4C6268", +">@ c #41555A", +",@ c #465D66", +"'@ c #485D66", +")@ c #4A5F6A", +"!@ c #3B4D54", +"~@ c #2D3A42", +"{@ c #28373E", +"]@ c #283840", +"^@ c #26363E", +"/@ c #24363E", +"(@ c #2B3840", +"_@ c #35454E", +":@ c #48575E", +"<@ c #4E606A", +"[@ c #4C606A", +"}@ c #465C64", +"|@ c #3D525C", +"1@ c #4A606A", +"2@ c #4A616A", +"3@ c #485B62", +"4@ c #435660", +"5@ c #3D4E56", +"6@ c #3D4C56", +"7@ c #4A5B64", +"8@ c #4C5F68", +"9@ c #4A5E68", +"0@ c #485F68", +"a@ c #506773", +"b@ c #526875", +"c@ c #566A77", +"d@ c #566975", +"e@ c #526570", +"f@ c #4E636C", +"g@ c #4A5F68", +"h@ c #546670", +"i@ c #566A72", +"j@ c #566B75", +"k@ c #546973", +"l@ c #50656E", +"m@ c #526971", +"n@ c #526A75", +"o@ c #546C77", +"p@ c #566D7B", +"q@ c #586D7B", +"r@ c #586C79", +"s@ c #546A73", +"t@ c #566B73", +"u@ c #566C77", +"v@ c #566D77", +"w@ c #566B77", +"x@ c #546777", +"y@ c #526673", +". + @ # $ % & * = - ; > , # > > > ' ) ! ~ ", +"{ ] ^ / ( _ : < [ } < < < < < < < | 1 2 3 ", +"4 5 6 7 8 9 0 a b b 0 0 0 c d b e f g h i ", +"j k l m n o ( p q r s s t u v w x y z A k ", +"B C D E F G H H I I J K J L M N O P Q R S ", +"T U V W X Y Z ` ...+.@.#.$.%.&.*.=.-.;.>.", +",.'.).y !.~.{.].^./.(.(._.:.<.[.}.|.1.2.3.", +";.4.5.6.7.8.9.9.9.0.a.a.9.b.c.d.e.f.1.2.g.", +"h.i.'.j.k.l.m.m.n.o.p.q.q.r.s.t.u.v.w.2.g.", +"h.x.1.y.z.A.B.C.D.E.F.G.H.I.J.K.L.M.N.U g.", +"O.P.1.Q.R.S.T.U.E.V.W.X.Y.Z.`. +u..+++@+#+", +"w.1.N.$+%+&+*+=+F.W.-+;+=+>+,+'+u.)+w.@+!+", +"w.P.~+{+]+&+*+^+/+X.;+(+^+>+_+:+<+[+}+|+1+", +"2+3+h.4+5+'+6+7+8+9+0+a+b+c+d+e+f+g+h+|+i+", +"O.j+k+l+m+n+o+p+q+r+s+t+t+o+u+v+w+x+y+@+z+", +"O.'.z+A+% B+C+D+D+E+F+F+F+G+H+I+J+K+L+@+i+", +"O.'.M+N+O+P+Q++ R+Q+S+S+S+T+U+V+O+W+X+'.Y+", +"O.L+Z+`+ @.@+@@@#@$@%@%@%@&@*@=@-@x.;@'.>@", +",@'@)@T !@J+~@{@]@{@^@/@^@(@_@:@<@[@X+}@|@", +"1@2@2@)@3@4@#+z `+5@z 6@z g.4@7@8@<@9@0@N.", +"a@b@c@d@e@f@8@i.g@i.i.i.i.8@<@h@i@j@d@k@l@", +"m@n@o@p@q@r@s@s@t@t@t@t@t@t@t@u@v@w@c@x@y@"}; diff --git a/gtk2_ardour/pixmaps/vslider00.xpm b/gtk2_ardour/pixmaps/vslider00.xpm new file mode 100644 index 0000000000..2a3687b937 --- /dev/null +++ b/gtk2_ardour/pixmaps/vslider00.xpm @@ -0,0 +1,197 @@ +/* XPM */ +static char * vslider00_xpm[] = { +"16 32 162 2", +" c None", +". c #7B7B7B", +"+ c #6C6C6C", +"@ c #626262", +"# c #585858", +"$ c #505050", +"% c #4B4B4B", +"& c #494949", +"* c #8C8C8C", +"= c #8E8E8E", +"- c #858585", +"; c #787878", +"> c #6D6D6D", +", c #666666", +"' c #616161", +") c #5C5C5C", +"! c #5B5B5B", +"~ c #595959", +"{ c #555555", +"] c #959595", +"^ c #ACACAC", +"/ c #A0A0A0", +"( c #949494", +"_ c #8D8D8D", +": c #888888", +"< c #848484", +"[ c #7E7E7E", +"} c #7C7C7C", +"| c #7A7A7A", +"1 c #797979", +"2 c #757575", +"3 c #676767", +"4 c #474747", +"5 c #9C9C9C", +"6 c #C2C2C2", +"7 c #BDBDBD", +"8 c #B9B9B9", +"9 c #B4B4B4", +"0 c #B1B1B1", +"a c #AEAEAE", +"b c #ABABAB", +"c c #A8A8A8", +"d c #A6A6A6", +"e c #A5A5A5", +"f c #A4A4A4", +"g c #9A9A9A", +"h c #323232", +"i c #9F9F9F", +"j c #D6D6D6", +"k c #D2D2D2", +"l c #D3D3D3", +"m c #D4D4D4", +"n c #D5D5D5", +"o c #D1D1D1", +"p c #232323", +"q c #DFDFDF", +"r c #DBDBDB", +"s c #E0E0E0", +"t c #E4E4E4", +"u c #E6E6E6", +"v c #E2E2E2", +"w c #DDDDDD", +"x c #D8D8D8", +"y c #AAAAAA", +"z c #777777", +"A c #1A1A1A", +"B c #F3F3F3", +"C c #D7D7D7", +"D c #D9D9D9", +"E c #CDCDCD", +"F c #737373", +"G c #151515", +"H c #F2F2F2", +"I c #DADADA", +"J c #D0D0D0", +"K c #CFCFCF", +"L c #CBCBCB", +"M c #C3C3C3", +"N c #999999", +"O c #131313", +"P c #F1F1F1", +"Q c #CACACA", +"R c #C6C6C6", +"S c #C1C1C1", +"T c #BBBBBB", +"U c #B8B8B8", +"V c #B3B3B3", +"W c #707070", +"X c #111111", +"Y c #F0F0F0", +"Z c #BCBCBC", +"` c #B6B6B6", +" . c #AFAFAF", +".. c #929292", +"+. c #828282", +"@. c #6B6B6B", +"#. c #101010", +"$. c #CECECE", +"%. c #C8C8C8", +"&. c #BEBEBE", +"*. c #A3A3A3", +"=. c #9B9B9B", +"-. c #919191", +";. c #7F7F7F", +">. c #0F0F0F", +",. c #EDEDED", +"'. c #CCCCCC", +"). c #C5C5C5", +"!. c #C0C0C0", +"~. c #BABABA", +"{. c #A1A1A1", +"]. c #B5B5B5", +"^. c #A2A2A2", +"/. c #9E9E9E", +"(. c #979797", +"_. c #C7C7C7", +":. c #C4C4C4", +"<. c #C9C9C9", +"[. c #8A8A8A", +"}. c #989898", +"|. c #7D7D7D", +"1. c #747474", +"2. c #6F6F6F", +"3. c #0B0B0B", +"4. c #868686", +"5. c #2C2C2C", +"6. c #0E0E0E", +"7. c #0D0D0D", +"8. c #0C0C0C", +"9. c #090909", +"0. c #010101", +"a. c #878787", +"b. c #353535", +"c. c #141414", +"d. c #020202", +"e. c #8F8F8F", +"f. c #8B8B8B", +"g. c #838383", +"h. c #606060", +"i. c #E3E3E3", +"j. c #727272", +"k. c #A7A7A7", +"l. c #DEDEDE", +"m. c #BFBFBF", +"n. c #B0B0B0", +"o. c #6A6A6A", +"p. c #F4F4F4", +"q. c #B7B7B7", +"r. c #696969", +"s. c #B2B2B2", +"t. c #6E6E6E", +"u. c #A9A9A9", +"v. c #909090", +"w. c #ADADAD", +"x. c #646464", +"y. c #656565", +"z. c #5A5A5A", +"A. c #545454", +"B. c #484848", +"C. c #404040", +"D. c #3E3E3E", +"E. c #0A0A0A", +" . + @ # $ % % % % % % % % & ", +"* = - ; > , ' ) ) ! ! ! ! ~ { ~ ", +"] ^ / ( _ : < [ } . | | 1 2 3 4 ", +"5 6 7 8 9 0 a b c d e e f g 2 h ", +"i j k k l m n n n n m m o 9 } p ", +"/ q r s t u u u v w r x m y z A ", +"e B C j x x x x D D n o E / F G ", +"e H j I r D j m k J K L M N F O ", +"e P o o K Q R S 7 T U V d * W X ", +"e Y K E Q R S Z ` .c / ..+.@.#.", +"e P $.L %.M &.U 0 y *.=.-.;., >.", +"f ,.'.).!.~.9 a c {.=.( * < W #.", +"{.s E &.]. .y c e ^.i /.(.+.+ #.", +"*.u L _.%.M :.:.R <._.S V [.@.#.", +"}./.+.|.;.. | ; z z 1.2.3 # 4 3.", +"4.5.#.#.#.>.>.>.6.6.6.7.8.3.9.0.", +"a.b.c.c.c.c.c.c.c.c.c.c.c.c.6.d.", +"}.*.e.e.e.e.= _ _ * f.[.: g.h.7.", +"*.i._.)._._.:.6 S &.T ` y ] j.#.", +"/ w %.].` ` ].9 9 V 0 .k._ @.#.", +"/ l.K ).M 6 S !.!.m.&.~.n.= o.#.", +"e P m J E E L Q Q <._.6 ` -.3 >.", +"e p.D J '.'.L Q <.%.).6 q.] r.>.", +"e B J T s.0 0 s.V s.s. .f - 3 >.", +"e H l E %.R R %.<.<.%.S s._ @.#.", +"e B C k K E '.L L '.'._.T =.t.>.", +"e B %.` ]. .b u.c k.k.k.e v.r.>.", +"e Y Q S ~.` s. .w.^ ^ b ^.- o.#.", +"^.w ~.0 ^ k.^./.=.N }.}.e.2 x.>.", +"( /.- 1 t.r.3 y.y.x.x.x.' # z.>.", +"~ 3 A.B.C.D.D.D.D.D.D.D.D.D.% 7.", +" c.8.E.9.9.9.9.9.9.9.9.9.9.3.d."}; diff --git a/gtk2_ardour/pixmaps/vslider01.xpm b/gtk2_ardour/pixmaps/vslider01.xpm new file mode 100644 index 0000000000..4afc6d1605 --- /dev/null +++ b/gtk2_ardour/pixmaps/vslider01.xpm @@ -0,0 +1,206 @@ +/* XPM */ +static char * vslider01_xpm[] = { +"3 200 3 1", +" c None", +". c #000000", +"+ c #969393", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+", +"..+"}; diff --git a/gtk2_ardour/playlist_selection.h b/gtk2_ardour/playlist_selection.h new file mode 100644 index 0000000000..af0031fec9 --- /dev/null +++ b/gtk2_ardour/playlist_selection.h @@ -0,0 +1,12 @@ +#ifndef __ardour_gtk_playlist_selection_h__ +#define __ardour_gtk_playlist_selection_h__ + +#include + +namespace ARDOUR { + class Playlist; +} + +struct PlaylistSelection : list {}; + +#endif /* __ardour_gtk_playlist_selection_h__ */ diff --git a/gtk2_ardour/playlist_selector.cc b/gtk2_ardour/playlist_selector.cc new file mode 100644 index 0000000000..d0796c0aa6 --- /dev/null +++ b/gtk2_ardour/playlist_selector.cc @@ -0,0 +1,249 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ + +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "playlist_selector.h" +#include "route_ui.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace std; +using namespace SigC; +using namespace Gtk; +using namespace ARDOUR; + +static const gchar *tree_display_titles[] = { + N_("Playlists grouped by track"), + 0 +}; + +PlaylistSelector::PlaylistSelector () + : ArdourDialog ("playlist selector"), + tree (internationalize (tree_display_titles)), + close_button (_("close")) +{ + rui = 0; + + set_position (GTK_WIN_POS_MOUSE); + set_name ("PlaylistSelectorWindow"); + set_title (_("ardour: playlists")); + set_modal(true); + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK); + set_usize (300, 200); + + scroller.add_with_viewport (tree); + scroller.set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + + close_button.clicked.connect (slot (*this, &PlaylistSelector::close_button_click)); + + vpacker.set_border_width (6); + vpacker.set_spacing (12); + vpacker.pack_start (scroller); + vpacker.pack_start (close_button, false, false); + + add (vpacker); +} + +PlaylistSelector::~PlaylistSelector () +{ + clear_map (); +} + +void +PlaylistSelector::clear_map () +{ + for (DSPL_Map::iterator x = dspl_map.begin(); x != dspl_map.end(); ++x) { + delete x->second; + } + dspl_map.clear (); +} + +void +PlaylistSelector::show_for (RouteUI* ruix) +{ + using namespace CTree_Helpers; + vector item; + RowList::iterator i; + RowList::iterator tmpi; + RowList::iterator others; + DiskStream* this_ds; + string str; + + rui = ruix; + + str = _("ardour: playlist for "); + str += rui->route().name(); + + set_title (str); + + clear_map (); + select_connection.disconnect (); + + /* ---------------------------------------- */ + /* XXX MAKE ME A FUNCTION (no CTree::clear() in gtkmm 1.2) */ + gtk_ctree_remove_node (tree.gtkobj(), NULL); + /* ---------------------------------------- */ + + session->foreach_playlist (this, &PlaylistSelector::add_playlist_to_map); + + this_ds = rui->get_diskstream(); + + item.clear(); + item.push_back (_("Other tracks")); + others = tree.rows().insert (tree.rows().begin(), Element (item)); + + for (DSPL_Map::iterator x = dspl_map.begin(); x != dspl_map.end(); ++x) { + + DiskStream* ds = session->diskstream_by_id (x->first); + + if (ds == 0) { + continue; + } + + /* add a node for the diskstream */ + + item.clear (); + + if (ds->name().empty()) { + item.push_back (_("unassigned")); + } else { + item.push_back (ds->name().c_str()); + } + + if (ds == this_ds) { + i = tree.rows().insert (tree.rows().begin(), + Gtk::CTree_Helpers::Element (item)); + } else { + i = others->subtree().insert (others->subtree().end(), + Gtk::CTree_Helpers::Element (item)); + } + + /* Now insert all the playlists for this diskstream/track in a subtree */ + + list *pls = x->second; + + for (list::iterator p = pls->begin(); p != pls->end(); ++p) { + + item.clear (); + item.push_back ((*p)->name().c_str()); + + tmpi = i->subtree().insert (i->subtree().end(), Element (item)); + + if (*p == this_ds->playlist()) { + (*tmpi).select (); + } + + (*tmpi).set_data (*p); + + } + + if (ds == this_ds) { + i->expand (); + } + } + + show_all (); + select_connection = tree.tree_select_row.connect (slot (*this, &PlaylistSelector::row_selected)); +} + +void +PlaylistSelector::add_playlist_to_map (Playlist *pl) +{ + AudioPlaylist* apl; + + if (pl->frozen()) { + return; + } + + if ((apl = dynamic_cast (pl)) == 0) { + return; + } + + DSPL_Map::iterator x; + + if ((x = dspl_map.find (apl->get_orig_diskstream_id())) == dspl_map.end()) { + + pair*> newp (apl->get_orig_diskstream_id(), new list); + + x = dspl_map.insert (dspl_map.end(), newp); + } + + x->second->push_back (pl); +} + +void +PlaylistSelector::set_session (Session* s) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &PlaylistSelector::set_session), s)); + + session = s; + + if (session) { + session->going_away.connect (bind (slot (*this, &PlaylistSelector::set_session), static_cast (0))); + } +} + +void +PlaylistSelector::close_button_click () +{ + rui = 0; + hide (); +} + +void +PlaylistSelector::row_selected (Gtk::CTree::Row row, gint col) +{ + Playlist *playlist; + + if ((playlist = (Playlist *) row.get_data()) != 0) { + + AudioTrack* at; + AudioPlaylist* apl; + + if ((at = dynamic_cast (&rui->route())) == 0) { + /* eh? */ + return; + } + + if ((apl = dynamic_cast (playlist)) == 0) { + /* eh? */ + return; + } + + at->disk_stream().use_playlist (apl); + + hide (); + } + +} + diff --git a/gtk2_ardour/playlist_selector.h b/gtk2_ardour/playlist_selector.h new file mode 100644 index 0000000000..5c36d6b0a3 --- /dev/null +++ b/gtk2_ardour/playlist_selector.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_playlist_selector_h__ +#define __ardour_playlist_selector_h__ + +#include +#include +#include + +#include + +namespace ARDOUR { + class Session; + class PluginManager; + class Plugin; +} + +class RouteUI; + +class PlaylistSelector : public ArdourDialog +{ + public: + PlaylistSelector (); + ~PlaylistSelector (); + + void set_session (ARDOUR::Session*); + void show_for (RouteUI*); + + private: + typedef std::map*> DSPL_Map; + + ARDOUR::Session* session; + Gtk::VBox vpacker; + Gtk::ScrolledWindow scroller; + Gtk::CTree tree; + Gtk::Button close_button; + DSPL_Map dspl_map; + RouteUI* rui; + + SigC::Connection select_connection; + + void add_playlist_to_map (ARDOUR::Playlist*); + void clear_map (); + void close_button_click (); + void row_selected (Gtk::CTree::Row, int32_t col); +}; + +#endif // __ardour_playlist_selector_h__ diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc new file mode 100644 index 0000000000..1ba8062f89 --- /dev/null +++ b/gtk2_ardour/plugin_selector.cc @@ -0,0 +1,418 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "ardour_ui.h" +#include "plugin_selector.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace ARDOUR; + +static const gchar *i_titles[] = { + N_("Available LADSPA plugins"), + N_("Type"), + N_("# Inputs"), + N_("# Outputs"), + 0 +}; + +#ifdef VST_SUPPORT +static const gchar *vst_titles[] = { + N_("Available VST plugins"), + N_("# Inputs"), + N_("# Outputs"), + 0 +}; +#endif + +static const gchar *o_titles[] = { + N_("To be added"), + 0 +}; + +PluginSelector::PluginSelector (PluginManager *mgr) + : ArdourDialog ("plugin selector"), + ladspa_display (_input_refiller, this, internationalize (i_titles), false, true), +#ifdef VST_SUPPORT + vst_display (_vst_refiller, this, internationalize (vst_titles), false, true), +#endif + o_selector (_output_refiller, this, internationalize (o_titles), false, true) +{ + set_position (GTK_WIN_POS_MOUSE); + set_name ("PluginSelectorWindow"); + set_title (_("ardour: plugins")); + set_modal(true); + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK); + + manager = mgr; + session = 0; + o_selected_plug = -1; + i_selected_plug = 0; + + Gtk::Button *btn_add = manage(new Gtk::Button(_("Add"))); + ARDOUR_UI::instance()->tooltips().set_tip(*btn_add, _("Add a plugin to the effect list")); + Gtk::Button *btn_remove = manage(new Gtk::Button(_("Remove"))); + ARDOUR_UI::instance()->tooltips().set_tip(*btn_remove, _("Remove a plugin from the effect list")); + Gtk::Button *btn_ok = manage(new Gtk::Button(_("OK"))); + Gtk::Button *btn_cancel = manage(new Gtk::Button(_("Cancel"))); + + Gtk::Button *btn_update = manage(new Gtk::Button(_("Update"))); + ARDOUR_UI::instance()->tooltips().set_tip(*btn_update, _("Update available plugins")); + + btn_ok->set_name("PluginSelectorButton"); + btn_cancel->set_name("PluginSelectorButton"); + btn_add->set_name("PluginSelectorButton"); + btn_remove->set_name("PluginSelectorButton"); + + Gtk::Table* table = manage(new Gtk::Table(7, 10)); + table->set_usize(750, 500); + table->attach(notebook, 0, 7, 0, 5); + + table->attach(*btn_add, 1, 2, 5, 6, GTK_FILL, 0, 5, 5); + table->attach(*btn_remove, 3, 4, 5, 6, GTK_FILL, 0, 5, 5); + table->attach(*btn_update, 5, 6, 5, 6, GTK_FILL, 0, 5, 5); + + table->attach(o_selector, 0, 7, 7, 9); + table->attach(*btn_ok, 1, 3, 9, 10, GTK_FILL, 0, 5, 5); + table->attach(*btn_cancel, 3, 4, 9, 10, GTK_FILL, 0, 5, 5); + add (*table); + + using namespace Gtk::Notebook_Helpers; + notebook.pages().push_back (TabElem (ladspa_display, _("LADSPA"))); +#ifdef VST_SUPPORT + if (Config->get_use_vst()) { + notebook.pages().push_back (TabElem (vst_display, _("VST"))); + } +#endif + + table->set_name("PluginSelectorTable"); + //ladspa_display.set_name("PluginSelectorDisplay"); + ladspa_display.clist().set_name("PluginSelectorList"); + o_selector.clist().set_name("PluginSelectorList"); + + ladspa_display.clist().column_titles_active(); + ladspa_display.clist().column(0).set_auto_resize (false); + ladspa_display.clist().column(0).set_width(470); + + ladspa_display.clist().column(1).set_auto_resize (true); + o_selector.clist().column(0).set_auto_resize (true); + + ladspa_display.selection_made.connect (slot(*this, &PluginSelector::i_plugin_selected)); + ladspa_display.choice_made.connect(slot(*this, &PluginSelector::i_plugin_chosen)); + ladspa_display.clist().click_column.connect(bind (slot(*this, &PluginSelector::column_clicked), ladspa_display.clist().gtkobj())); +#ifdef VST_SUPPORT + if (Config->get_use_vst()) { + vst_display.selection_made.connect (slot(*this, &PluginSelector::i_plugin_selected)); + vst_display.choice_made.connect(slot(*this, &PluginSelector::i_plugin_chosen)); + vst_display.clist().click_column.connect(bind (slot(*this, &PluginSelector::column_clicked), vst_display.clist().gtkobj())); + } +#endif + o_selector.selection_made.connect(slot(*this, &PluginSelector::o_plugin_selected)); + o_selector.choice_made.connect(slot(*this,&PluginSelector::o_plugin_chosen)); + btn_update->clicked.connect (slot(*this, &PluginSelector::btn_update_clicked)); + btn_add->clicked.connect(slot(*this, &PluginSelector::btn_add_clicked)); + btn_remove->clicked.connect(slot(*this, &PluginSelector::btn_remove_clicked)); + btn_ok->clicked.connect(slot(*this, &PluginSelector::btn_ok_clicked)); + btn_cancel->clicked.connect(slot(*this,&PluginSelector::btn_cancel_clicked)); + delete_event.connect (slot (*this, &PluginSelector::wm_close)); + +} + +void +PluginSelector::set_session (Session* s) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &PluginSelector::set_session), s)); + + session = s; + + if (session) { + session->going_away.connect (bind (slot (*this, &PluginSelector::set_session), static_cast (0))); + } +} + +void +PluginSelector::_input_refiller (Gtk::CList &list, void *arg) +{ + ((PluginSelector *) arg)->input_refiller (list); +} + +void +PluginSelector::_output_refiller (Gtk::CList &list, void *arg) +{ + ((PluginSelector *) arg)->output_refiller (list); +} + +int compare(const void *left, const void *right) +{ + return strcmp(*((char**)left), *((char**)right)); +} + +void +PluginSelector::input_refiller (Gtk::CList &clist) +{ + const gchar *rowdata[4]; + guint row; + list &plugs = manager->ladspa_plugin_info (); + list::iterator i; + char ibuf[16], obuf[16]; + + // Insert into GTK list + for (row = 0, i=plugs.begin(); i != plugs.end(); ++i, ++row) { + rowdata[0] = (*i)->name.c_str(); + rowdata[1] = (*i)->category.c_str(); + + snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs); + snprintf (obuf, sizeof(obuf)-1, "%d", (*i)->n_outputs); + rowdata[2] = ibuf; + rowdata[3] = obuf; + + clist.insert_row (row, rowdata); + clist.rows().back().set_data (*i); + } + + clist.set_sort_column (0); + clist.sort (); +} + +#ifdef VST_SUPPORT + +void +PluginSelector::_vst_refiller (Gtk::CList &list, void *arg) +{ + ((PluginSelector *) arg)->vst_refiller (list); +} + +void +PluginSelector::vst_refiller (Gtk::CList &clist) +{ + const gchar *rowdata[3]; + guint row; + list &plugs = manager->vst_plugin_info (); + list::iterator i; + char ibuf[16], obuf[16]; + + if (!Config->get_use_vst()) { + return; + } + + // Insert into GTK list + + for (row = 0, i = plugs.begin(); i != plugs.end(); ++i, ++row) { + rowdata[0] = (*i)->name.c_str(); + + snprintf (ibuf, sizeof(ibuf)-1, "%d", (*i)->n_inputs); + snprintf (obuf, sizeof(obuf)-1, "%d", (*i)->n_outputs); + rowdata[1] = ibuf; + rowdata[2] = obuf; + + clist.insert_row (row, rowdata); + clist.rows().back().set_data (*i); + } + + clist.set_sort_column (0); + clist.sort (); +} +#endif + +void +PluginSelector::output_refiller (Gtk::CList &clist) +{ + const gchar *rowdata[2]; + guint row; + list::iterator i; + + // Insert into GTK list + + for (row = 0, i = added_plugins.begin(); i != added_plugins.end(); ++i, ++row){ + rowdata[0] = (*i)->name.c_str(); + clist.insert_row (row, rowdata); + clist.rows().back().set_data (*i); + } +} + +void +PluginSelector::i_plugin_chosen (Gtkmmext::Selector *selector, + Gtkmmext::SelectionResult *res) +{ + if (res) { + // get text for name column (0) + i_selected_plug = static_cast (selector->clist().row(res->row).get_data()); + //i_selected_plug = *res->text; + } else { + i_selected_plug = 0; + } +} + +void +PluginSelector::i_plugin_selected (Gtkmmext::Selector *selector, + Gtkmmext::SelectionResult *res) +{ + if (res) { + added_plugins.push_back (static_cast (selector->clist().row(res->row).get_data())); + //added_plugins.push_back(*(res->text)); + o_selector.rescan(); + } +} + +void +PluginSelector::o_plugin_chosen (Gtkmmext::Selector *selector, + Gtkmmext::SelectionResult *res) +{ + if (res && res->text) { + o_selected_plug = res->row; + } else { + o_selected_plug = -1; + } + +} + +void +PluginSelector::o_plugin_selected (Gtkmmext::Selector *selector, + Gtkmmext::SelectionResult *res) +{ + if(res && res->text){ + gint row = 0; + list::iterator i = added_plugins.begin(); + while (row < res->row){ + i++; + row++; + } + added_plugins.erase(i); + o_selector.rescan(); + o_selected_plug = -1; + } +} + +void +PluginSelector::use_plugin (PluginInfo* pi) +{ + list::iterator i; + + if (pi == 0 || session == 0) { + return; + } + + Plugin *plugin = manager->load (*session, pi); + + if (plugin) { + PluginCreated (plugin); + } +} + +void +PluginSelector::btn_add_clicked() +{ + if (i_selected_plug) { + added_plugins.push_back (i_selected_plug); + o_selector.rescan(); + } +} + +void +PluginSelector::btn_remove_clicked() +{ + if (o_selected_plug > -1){ + gint row = 0; + list::iterator i = added_plugins.begin(); + while(row < o_selected_plug){ + i++; + row++; + } + added_plugins.erase(i); + o_selector.rescan(); + o_selected_plug = -1; + } +} + +// Adds a plugin, and closes the window. +void +PluginSelector::btn_ok_clicked() +{ + using namespace Gtk::CList_Helpers; + + list::iterator i; + + for (i = added_plugins.begin(); i != added_plugins.end(); ++i){ + use_plugin (*i); + } + + hide(); + added_plugins.clear(); + o_selector.rescan(); + i_selected_plug = 0; + o_selected_plug = -1; + + SelectionList s_list = ladspa_display.clist().selection(); + SelectionList::iterator s = s_list.begin(); + if (s != s_list.end()) { + (*s).unselect(); + } + +#ifdef VST_SUPPORT + SelectionList v_list = vst_display.clist().selection(); + SelectionList::iterator v = v_list.begin(); + if (v != v_list.end()) { + (*v).unselect(); + } +#endif +} + +void +PluginSelector::btn_cancel_clicked() +{ + hide(); + added_plugins.clear(); + o_selector.rescan(); + i_selected_plug = 0; + o_selected_plug = -1; +} + +void +PluginSelector::btn_update_clicked() +{ + manager->refresh (); + ladspa_display.rescan (); +} + +gint +PluginSelector::wm_close(GdkEventAny* ev) +{ + btn_cancel_clicked(); + return TRUE; +} + +void +PluginSelector::column_clicked (int column, GtkCList* clist) +{ + gtk_clist_set_sort_column (clist, column); + gtk_clist_sort (clist); +} diff --git a/gtk2_ardour/plugin_selector.h b/gtk2_ardour/plugin_selector.h new file mode 100644 index 0000000000..d1d0a54747 --- /dev/null +++ b/gtk2_ardour/plugin_selector.h @@ -0,0 +1,92 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_plugin_selector_h__ +#define __ardour_plugin_selector_h__ + +#include +#include +#include + +#include + +namespace ARDOUR { + class Session; + class PluginManager; + class Plugin; +} + +class PluginSelector : public ArdourDialog +{ + public: + PluginSelector (ARDOUR::PluginManager *); + SigC::Signal1 PluginCreated; + + void set_session (ARDOUR::Session*); + + private: + ARDOUR::Session* session; + Gtk::Notebook notebook; + + // page 1 + Gtkmmext::Selector ladspa_display; + void column_clicked (int column, GtkCList* clist); + +#ifdef VST_SUPPORT + // page 2 + Gtkmmext::Selector vst_display; + static void _vst_refiller (Gtk::CList &, void *); + void vst_refiller (Gtk::CList &); +#endif + Gtkmmext::Selector o_selector; + + ARDOUR::PluginInfo* i_selected_plug; + + // We need an integer for the output side because + // the name isn't promised to be unique. + gint o_selected_plug; + + ARDOUR::PluginManager *manager; + list added_plugins; + + static void _input_refiller (Gtk::CList &, void *); + static void _output_refiller (Gtk::CList &, void *); + + void input_refiller (Gtk::CList &); + void output_refiller (Gtk::CList &); + void i_plugin_selected (Gtkmmext::Selector *selector, + Gtkmmext::SelectionResult *res); + void i_plugin_chosen (Gtkmmext::Selector *selector, + Gtkmmext::SelectionResult *res); + void o_plugin_selected (Gtkmmext::Selector *selector, + Gtkmmext::SelectionResult *res); + void o_plugin_chosen (Gtkmmext::Selector *selector, + Gtkmmext::SelectionResult *res); + + void btn_add_clicked(); + void btn_remove_clicked(); + void btn_ok_clicked(); + void btn_update_clicked(); + void btn_apply_clicked(); + void btn_cancel_clicked(); + void use_plugin (ARDOUR::PluginInfo*); + gint wm_close(GdkEventAny* ev); +}; + +#endif // __ardour_plugin_selector_h__ diff --git a/gtk2_ardour/plugin_ui.cc b/gtk2_ardour/plugin_ui.cc new file mode 100644 index 0000000000..3932541ebc --- /dev/null +++ b/gtk2_ardour/plugin_ui.cc @@ -0,0 +1,933 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#ifdef VST_SUPPORT +#include +#endif + +#include + +#include "ardour_ui.h" +#include "prompter.h" +#include "plugin_ui.h" +#include "utils.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; +using namespace Gtkmmext; +using namespace Gtk; +using namespace SigC; + +PluginUIWindow::PluginUIWindow (AudioEngine &engine, PluginInsert& insert, bool scrollable) + : ArdourDialog ("plugin ui") +{ + if (insert.plugin().has_editor()) { + +#ifdef VST_SUPPORT + + VSTPlugin* vp; + + if ((vp = dynamic_cast (&insert.plugin())) != 0) { + + + VSTPluginUI* vpu = new VSTPluginUI (insert, *vp); + + _pluginui = vpu; + add (*vpu); + vpu->package (*this); + + } else { +#endif + error << _("unknown type of editor-supplying plugin (note: no VST support in this version of ardour)") + << endmsg; + throw failed_constructor (); +#ifdef VST_SUPPORT + } +#endif + + } else { + + PluginUI* pu = new PluginUI (engine, insert, scrollable); + + _pluginui = pu; + add (*pu); + + map_event.connect (slot (*pu, &PluginUI::start_updating)); + unmap_event.connect (slot (*pu, &PluginUI::stop_updating)); + } + + set_position (GTK_WIN_POS_MOUSE); + set_name ("PluginEditor"); + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK); + + delete_event.connect (bind (slot (just_hide_it), reinterpret_cast (this))); + insert.GoingAway.connect (slot (*this, &PluginUIWindow::plugin_going_away)); + + if (scrollable) { + gint h = _pluginui->get_preferred_height (); + if (h > 600) h = 600; + set_default_size (450, h); + } +} + +PluginUIWindow::~PluginUIWindow () +{ +} + +PluginUI::PluginUI (AudioEngine &engine, PluginInsert& pi, bool scrollable) + : PlugUIBase (pi), + engine(engine), + button_table (initial_button_rows, initial_button_cols), + output_table (initial_output_rows, initial_output_cols), + automation_menu (0), + is_scrollable(scrollable) +{ + set_name ("PluginEditor"); + set_border_width (10); + set_homogeneous (false); + + settings_box.set_homogeneous (false); + + HBox* constraint_hbox = manage (new HBox); + HBox* smaller_hbox = manage (new HBox); + + smaller_hbox->pack_start (combo, false, false); + smaller_hbox->pack_start (save_button, false, false); + + constraint_hbox->set_spacing (10); + constraint_hbox->pack_start (*smaller_hbox, true, false); + constraint_hbox->pack_end (bypass_button, false, false); + +// name_ebox.add (*text_hbox); +// info_vbox.pack_start (name_ebox, false, false); +// info_vbox.pack_start (makerinfo_label, false, false); +// info_vbox.pack_start (paraminfo_label, false, false, 5); + +// settings_box.pack_start (info_vbox, false, false, 10); + settings_box.pack_end (*constraint_hbox, false, false); + + pack_start (settings_box, false, false); + + if ( is_scrollable ) { + scroller.set_policy (GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + scroller.set_name ("PluginEditor"); + scroller_view.set_name("PluginEditor"); + scroller_view.add (hpacker); + scroller.add (scroller_view); + + pack_start (scroller, true, true); + + } + else { + pack_start (hpacker, false, false); + + // this is a hack to get the theme right + name_ebox.set_name ("PluginNameBox"); + } + + insert.active_changed.connect (slot (*this, &PluginUI::redirect_active_changed)); + bypass_button.set_active (!insert.active()); + + build (engine); +} + +PluginUI::~PluginUI () +{ + if (output_controls.size() > 0) { + screen_update_connection.disconnect(); + } +} + +void +PluginUI::build (AudioEngine &engine) + +{ + guint32 i = 0; + guint32 x = 0; + Frame* frame; + Frame* bt_frame; + VBox* box; + char info[32]; + int output_row, output_col; + int button_row, button_col; + int output_rows, output_cols; + int button_rows, button_cols; + guint32 n_ins=0, n_outs = 0; + + prefheight = 30; + hpacker.set_spacing (10); + + output_rows = initial_output_rows; + output_cols = initial_output_cols; + button_rows = initial_button_rows; + button_cols = initial_button_cols; + output_row = 0; + button_row = 0; + output_col = 0; + button_col = 0; + + button_table.set_homogeneous (false); + button_table.set_row_spacings (2); + button_table.set_col_spacings (2); + output_table.set_homogeneous (true); + output_table.set_row_spacings (2); + output_table.set_col_spacings (2); + button_table.set_border_width (5); + output_table.set_border_width (5); + + hpacker.set_border_width (10); + + bt_frame = manage (new Frame); + bt_frame->set_name ("BaseFrame"); + bt_frame->add (button_table); + hpacker.pack_start(*bt_frame, true, true); + + box = manage (new VBox); + frame = manage (new Frame); + frame->set_name ("BaseFrame"); + frame->add (*box); + hpacker.pack_start(*frame, true, true); + + box->set_border_width (5); + box->set_spacing (1); + + /* find all ports. build control elements for all appropriate control ports */ + + for (i = 0; i < plugin.parameter_count(); ++i) { + + if (plugin.parameter_is_control (i)) { + + ControlUI* cui; + + /* if we are scrollable, just use one long column */ + + if (!is_scrollable) { + if (x++ > 7){ + frame = manage (new Frame); + frame->set_name ("BaseFrame"); + box = manage (new VBox); + + box->set_border_width (5); + box->set_spacing (1); + + frame->add (*box); + hpacker.pack_start(*frame,true,true); + + x = 0; + } + } + + /* Don't show latency control ports */ + + if (plugin.describe_parameter (i) == X_("latency")) { + continue; + } + + if ((cui = build_control_ui (engine, i, plugin.get_nth_midi_control (i))) == 0) { + error << compose(_("Plugin Editor: could not build control element for port %1"), i) << endmsg; + continue; + } + + if (cui->control || cui->clickbox || cui->combo) { + + box->pack_start (*cui, false, false); + + } else if (cui->button) { + + if (button_row == button_rows) { + button_row = 0; + if (++button_col == button_cols) { + button_cols += 2; + button_table.resize (button_rows, button_cols); + } + } + + button_table.attach (*cui, button_col, button_col + 1, button_row, button_row+1, + GTK_FILL|GTK_EXPAND, 0); + button_row++; + + } else if (cui->display) { + + if (output_row == output_rows) { + output_row = 0; + if (++output_col == output_cols) { + output_cols += 2; + output_table.resize (output_rows, output_cols); + } + } + + output_table.attach (*cui, output_col, output_col + 1, output_row, output_row+1, + GTK_FILL|GTK_EXPAND, 0); + + output_row++; + } + + /* HACK: ideally the preferred height would be queried from + the complete hpacker, but I can't seem to get that + information in time, so this is an estimation + */ + + prefheight += 30; + + } + } + + n_ins = plugin.get_info().n_inputs; + n_outs = plugin.get_info().n_outputs; + + if (box->children().empty()) { + hpacker.remove (*frame); + } + + if (button_table.children().empty()) { + hpacker.remove (*bt_frame); + } + + if (!output_table.children().empty()) { + frame = manage (new Frame); + frame->set_name ("BaseFrame"); + frame->add (output_table); + hpacker.pack_end (*frame, true, true); + } + + output_update (); + + string pname = plugin.name(); + + if (pname.length() > 24) { + pname = pname.substr (0, 24); + pname += "..."; + ARDOUR_UI::instance()->tooltips().set_tip(name_ebox, plugin.name()); + } + + + nameinfo_label.set_text (pname); + nameinfo_label.set_name ("PluginNameInfo"); + nameinfo_label.set_alignment (0.0, 0.0); + + string maker = plugin.maker(); + string::size_type email_pos; + + if ((email_pos = maker.find_first_of ('<')) != string::npos) { + maker = maker.substr (0, email_pos - 1); + } + + if (maker.length() > 32) { + maker = maker.substr (0, 32); + maker += " ..."; + } + + makerinfo_label.set_text (maker); + makerinfo_label.set_name ("PluginMakerInfo"); + makerinfo_label.set_alignment (0.0, 0.0); + + snprintf (info, sizeof(info),"[ %u %s | %u %s ]", + n_ins, ngettext(_("in"), _("ins"), n_ins), + n_outs, ngettext(_("out"), _("outs"), n_outs)); + paraminfo_label.set_text (info); + paraminfo_label.set_name ("PluginParameterInfo"); + paraminfo_label.set_alignment (0.0, 0.0); + + output_table.show_all (); + button_table.show_all (); +} + +PluginUI::ControlUI::ControlUI () + : automate_button (X_("")) // force creation of a label +{ + automate_button.set_name ("PluginAutomateButton"); + ARDOUR_UI::instance()->tooltips().set_tip (automate_button, + _("automation control")); + + /* don't fix the height, it messes up the bar controllers */ + + set_usize_to_display_given_text (automate_button, X_("longenuff"), 2, -1); + + ignore_change = 0; + display = 0; + button = 0; + control = 0; + clickbox = 0; + adjustment = 0; + meterinfo = 0; +} + +PluginUI::ControlUI::~ControlUI() +{ + if (adjustment) { + delete adjustment; + } + + if (meterinfo) { + delete meterinfo->meter; + delete meterinfo; + } +} + +void +PluginUI::automation_state_changed (ControlUI* cui) +{ + /* update button label */ + + switch (insert.get_port_automation_state (cui->port_index) & (Off|Play|Touch|Write)) { + case Off: + static_cast(cui->automate_button.get_child())->set_text (_("off")); + break; + case Play: + static_cast(cui->automate_button.get_child())->set_text (_("play")); + break; + case Write: + static_cast(cui->automate_button.get_child())->set_text (_("write")); + break; + case Touch: + static_cast(cui->automate_button.get_child())->set_text (_("touch")); + break; + default: + static_cast(cui->automate_button.get_child())->set_text (_("???")); + break; + } +} + + +static void integer_printer (char buf[32], Adjustment &adj, void *arg) +{ + snprintf (buf, 32, "%.0f", adj.get_value()); +} + +void +PluginUI::print_parameter (char *buf, uint32_t len, uint32_t param) +{ + plugin.print_parameter (param, buf, len); +} + +PluginUI::ControlUI* +PluginUI::build_control_ui (AudioEngine &engine, guint32 port_index, MIDI::Controllable* mcontrol) + +{ + ControlUI* control_ui; + Plugin::ParameterDescriptor desc; + + plugin.get_parameter_descriptor (port_index, desc); + + control_ui = manage (new ControlUI ()); + control_ui->adjustment = 0; + control_ui->combo = 0; + control_ui->combo_map = 0; + control_ui->port_index = port_index; + control_ui->update_pending = false; + control_ui->label.set_text (desc.label); + control_ui->label.set_alignment (0.0, 0.5); + control_ui->label.set_name ("PluginParameterLabel"); + + control_ui->set_spacing (5); + + if (plugin.parameter_is_input (port_index)) { + + LadspaPlugin* lp; + + if ((lp = dynamic_cast(&plugin)) != 0) { + + lrdf_defaults* defaults = lrdf_get_scale_values(lp->unique_id(), port_index); + + if (defaults && defaults->count > 0) { + + control_ui->combo = new Gtk::Combo; + control_ui->combo->set_value_in_list(true, false); + control_ui->combo->set_popdown_strings(setup_scale_values(port_index, control_ui)); + control_ui->combo->get_popwin()->unmap_event.connect(bind (slot (*this, &PluginUI::control_combo_changed), control_ui)); + plugin.ParameterChanged.connect (bind (slot (*this, &PluginUI::parameter_changed), control_ui)); + control_ui->pack_start(control_ui->label, true, true); + control_ui->pack_start(*control_ui->combo, false, true); + + update_control_display(control_ui); + + lrdf_free_setting_values(defaults); + return control_ui; + } + } + + if (desc.toggled) { + + /* Build a button */ + + control_ui->button = manage (new ToggleButton ()); + control_ui->button->set_name ("PluginEditorButton"); + control_ui->button->set_usize (20, 20); + + control_ui->pack_start (control_ui->label, true, true); + control_ui->pack_start (*control_ui->button, false, true); + control_ui->pack_start (control_ui->automate_button, false, false); + + control_ui->button->clicked.connect (bind (slot (*this, &PluginUI::control_port_toggled), control_ui)); + + if(plugin.get_parameter (port_index) == 1){ + control_ui->button->set_active(true); + } + + return control_ui; + } + + control_ui->adjustment = new Adjustment (0, 0, 0, 0, 0); + + /* XXX this code is not right yet, because it doesn't handle + the absence of bounds in any sensible fashion. + */ + + control_ui->adjustment->set_lower (desc.lower); + control_ui->adjustment->set_upper (desc.upper); + + control_ui->logarithmic = desc.logarithmic; + if (control_ui->logarithmic) { + if (control_ui->adjustment->get_lower() == 0.0) { + control_ui->adjustment->set_lower (control_ui->adjustment->get_upper()/10000); + } + control_ui->adjustment->set_upper (log(control_ui->adjustment->get_upper())); + control_ui->adjustment->set_lower (log(control_ui->adjustment->get_lower())); + } + + float delta = desc.upper - desc.lower; + + control_ui->adjustment->set_page_size (delta/100.0); + control_ui->adjustment->set_step_increment (desc.step); + control_ui->adjustment->set_page_increment (desc.largestep); + + if (desc.integer_step) { + control_ui->clickbox = new ClickBox (control_ui->adjustment, "PluginUIClickBox"); + Gtkmmext::set_usize_to_display_given_text (*control_ui->clickbox, "g9999999", 2, 2); + control_ui->clickbox->set_print_func (integer_printer, 0); + } else { +// control_ui->control = new HSliderController (ARDOUR_UI::instance()->plugin_ui_slider_pix(), +// control_ui->adjustment, +// mcontrol); + + SigC::Slot2 pslot = SigC::bind (slot (*this, &PluginUI::print_parameter), (uint32_t) port_index); + + control_ui->control = new BarController (*control_ui->adjustment, mcontrol, pslot); + control_ui->control->set_usize (200, 15); + control_ui->control->set_name (X_("PluginSlider")); + control_ui->control->set_style (BarController::LeftToRight); + control_ui->control->set_use_parent (true); + + control_ui->control->get_spin_button().focus_in_event.connect (slot (*this, &PluginUI::entry_focus_event)); + control_ui->control->get_spin_button().focus_out_event.connect (slot (*this, &PluginUI::entry_focus_event)); + + control_ui->control->StartGesture.connect (bind (slot (*this, &PluginUI::start_touch), control_ui)); + control_ui->control->StopGesture.connect (bind (slot (*this, &PluginUI::stop_touch), control_ui)); + + } + + if (control_ui->logarithmic) { + control_ui->adjustment->set_value(log(plugin.get_parameter(port_index))); + } else{ + control_ui->adjustment->set_value(plugin.get_parameter(port_index)); + } + + /* XXX memory leak: SliderController not destroyed by ControlUI + destructor, and manage() reports object hierarchy + ambiguity. + */ + + control_ui->pack_start (control_ui->label, true, true); + if (desc.integer_step) { + control_ui->pack_start (*control_ui->clickbox, false, false); + } else { + control_ui->pack_start (*control_ui->control, false, false); + } + + control_ui->pack_start (control_ui->automate_button, false, false); + control_ui->adjustment->value_changed.connect (bind (slot (*this, &PluginUI::control_adjustment_changed), control_ui)); + control_ui->automate_button.clicked.connect (bind (slot (*this, &PluginUI::astate_clicked), control_ui, (uint32_t) port_index)); + + automation_state_changed (control_ui); + + plugin.ParameterChanged.connect (bind (slot (*this, &PluginUI::parameter_changed), control_ui)); + insert.automation_list (port_index).automation_state_changed.connect + (bind (slot (*this, &PluginUI::automation_state_changed), control_ui)); + + } else if (plugin.parameter_is_output (port_index)) { + + control_ui->display = manage (new EventBox); + control_ui->display->set_name ("ParameterValueDisplay"); + + control_ui->display_label = manage (new Label); + control_ui->display_label->set_name ("ParameterValueDisplay"); + + control_ui->display->add (*control_ui->display_label); + Gtkmmext::set_usize_to_display_given_text (*control_ui->display, "g999999", 2, 2); + + control_ui->display->show_all (); + + /* set up a meter */ + /* TODO: only make a meter if the port is Hinted for it */ + + MeterInfo * info = new MeterInfo(port_index); + control_ui->meterinfo = info; + + info->meter = new FastMeter (100, 5, FastMeter::Horizontal); + + info->min_unbound = desc.min_unbound; + info->max_unbound = desc.max_unbound; + + info->min = desc.lower; + info->max = desc.upper; + + control_ui->vbox = manage (new VBox); + + control_ui->vbox->pack_start (control_ui->label, false, false); + control_ui->vbox->pack_start (*info->meter, false, false); + + control_ui->pack_start (*control_ui->vbox, false, false); + control_ui->pack_start (*control_ui->display, false, false); + + control_ui->meterinfo->meter->show_all(); + control_ui->meterinfo->packed = true; + + output_controls.push_back (control_ui); + } + + plugin.ParameterChanged.connect (bind (slot (*this, &PluginUI::parameter_changed), control_ui)); + return control_ui; +} + +void +PluginUI::start_touch (PluginUI::ControlUI* cui) +{ + insert.automation_list (cui->port_index).start_touch (); +} + +void +PluginUI::stop_touch (PluginUI::ControlUI* cui) +{ + insert.automation_list (cui->port_index).stop_touch (); +} + +void +PluginUI::astate_clicked (ControlUI* cui, uint32_t port) +{ + using namespace Menu_Helpers; + + if (automation_menu == 0) { + automation_menu = manage (new Menu); + automation_menu->set_name ("ArdourContextMenu"); + } + + MenuList& items (automation_menu->items()); + + items.clear (); + items.push_back (MenuElem (_("off"), + bind (slot (*this, &PluginUI::set_automation_state), (AutoState) Off, cui))); + items.push_back (MenuElem (_("play"), + bind (slot (*this, &PluginUI::set_automation_state), (AutoState) Play, cui))); + items.push_back (MenuElem (_("write"), + bind (slot (*this, &PluginUI::set_automation_state), (AutoState) Write, cui))); + items.push_back (MenuElem (_("touch"), + bind (slot (*this, &PluginUI::set_automation_state), (AutoState) Touch, cui))); + + automation_menu->popup (1, 0); +} + +void +PluginUI::set_automation_state (AutoState state, ControlUI* cui) +{ + insert.set_port_automation_state (cui->port_index, state); +} + +void +PluginUI::control_adjustment_changed (ControlUI* cui) +{ + if (cui->ignore_change) { + return; + } + + double value = cui->adjustment->get_value(); + + if (cui->logarithmic) { + value = exp(value); + } + + insert.set_parameter (cui->port_index, (float) value); +} + +void +PluginUI::parameter_changed (uint32_t abs_port_id, float val, ControlUI* cui) +{ + if (cui->port_index == abs_port_id) { + if (!cui->update_pending) { + cui->update_pending = true; + Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &PluginUI::update_control_display), cui)); + } + } +} + +void +PluginUI::update_control_display (ControlUI* cui) +{ + /* XXX how do we handle logarithmic stuff here ? */ + + cui->update_pending = false; + + float val = plugin.get_parameter (cui->port_index); + + cui->ignore_change++; + if (cui->combo) { + map::iterator it; + for (it = cui->combo_map->begin(); it != cui->combo_map->end(); ++it) { + if (it->second == val) { + cui->combo->get_entry()->set_text(it->first); + break; + } + } + } else if (cui->adjustment == 0) { + + if (val > 0.5) { + cui->button->set_active (true); + } else { + cui->button->set_active (false); + } + + } else { + if (cui->logarithmic) { + val = log(val); + } + if (val != cui->adjustment->get_value()) { + cui->adjustment->set_value (val); + } + } + cui->ignore_change--; +} + +void +PluginUI::control_port_toggled (ControlUI* cui) +{ + if (!cui->ignore_change) { + insert.set_parameter (cui->port_index, cui->button->get_active()); + } +} + +gint +PluginUI::control_combo_changed (GdkEventAny* ignored, ControlUI* cui) +{ + if (!cui->ignore_change) { + string value = cui->combo->get_entry()->get_text(); + map mapping = *cui->combo_map; + insert.set_parameter (cui->port_index, mapping[value]); + } + + return FALSE; +} + +void +PluginUIWindow::plugin_going_away (ARDOUR::Redirect* ignored) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &PluginUIWindow::plugin_going_away), ignored)); + + _pluginui->stop_updating(0); + delete_when_idle (this); +} + +gint +PluginUI::entry_focus_event (GdkEventFocus* ev) +{ + if (ev->in) { + ARDOUR_UI::instance()->allow_focus (true); + } else { + ARDOUR_UI::instance()->allow_focus (false); + } + return TRUE; +} + +void +PluginUI::redirect_active_changed (Redirect* r, void* src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &PluginUI::redirect_active_changed), r, src)); + + bypass_button.set_active (!r->active()); +} + +gint +PluginUI::start_updating (GdkEventAny *ev) +{ + if (output_controls.size() > 0 ) { + screen_update_connection.disconnect(); + screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect + (slot (*this, &PluginUI::output_update)); + } + return FALSE; +} + +gint +PluginUI::stop_updating (GdkEventAny *ev) +{ + if (output_controls.size() > 0 ) { + screen_update_connection.disconnect(); + } + return FALSE; +} + +void +PluginUI::output_update () +{ + for (vector::iterator i = output_controls.begin(); i != output_controls.end(); ++i) { + float val = plugin.get_parameter ((*i)->port_index); + char buf[32]; + snprintf (buf, sizeof(buf), "%.2f", val); + (*i)->display_label->set_text (buf); + + /* autoscaling for the meter */ + if ((*i)->meterinfo && (*i)->meterinfo->packed) { + + if (val < (*i)->meterinfo->min) { + if ((*i)->meterinfo->min_unbound) + (*i)->meterinfo->min = val; + else + val = (*i)->meterinfo->min; + } + + if (val > (*i)->meterinfo->max) { + if ((*i)->meterinfo->max_unbound) + (*i)->meterinfo->max = val; + else + val = (*i)->meterinfo->max; + } + + if ((*i)->meterinfo->max > (*i)->meterinfo->min ) { + float lval = (val - (*i)->meterinfo->min) / ((*i)->meterinfo->max - (*i)->meterinfo->min) ; + (*i)->meterinfo->meter->set (lval ); + } + } + } +} + +list +PluginUI::setup_scale_values(guint32 port_index, ControlUI* cui) +{ + list enums; + LadspaPlugin* lp = dynamic_cast (&plugin); + + cui->combo_map = new map; + lrdf_defaults* defaults = lrdf_get_scale_values(lp->unique_id(), port_index); + if (defaults) { + for (uint32_t i = 0; i < defaults->count; ++i) { + enums.push_back(defaults->items[i].label); + pair newpair; + newpair.first = defaults->items[i].label; + newpair.second = defaults->items[i].value; + cui->combo_map->insert(newpair); + } + + lrdf_free_setting_values(defaults); + } + + return enums; +} + +PlugUIBase::PlugUIBase (PluginInsert& pi) + : insert (pi), + plugin (insert.plugin()), + save_button(_("save")), + bypass_button (_("bypass")) +{ + combo.set_value_in_list(true,true); + combo.set_use_arrows(true); + combo.set_use_arrows_always(true); + combo.set_popdown_strings(plugin.get_presets()); + combo.get_entry()->set_text(""); + combo.get_popwin()->unmap_event.connect(slot (*this, &PlugUIBase::setting_selected)); + + save_button.set_name ("PluginSaveButton"); + save_button.clicked.connect(slot (*this, &PlugUIBase::save_plugin_setting)); + + bypass_button.set_name ("PluginBypassButton"); + bypass_button.toggled.connect (slot (*this, &PlugUIBase::bypass_toggled)); +} + +gint +PlugUIBase::setting_selected(GdkEventAny* ignored) +{ + Entry* entry = combo.get_entry(); + if (entry->get_text().length() > 0) { + if (!plugin.load_preset(entry->get_text())) { + warning << compose(_("Plugin preset %1 not found"), entry->get_text()) << endmsg; + } + } + + return FALSE; +} + +void +PlugUIBase::save_plugin_setting () +{ + ArdourPrompter prompter (true); + prompter.set_prompt(_("Name for plugin settings:")); + + prompter.show_all(); + prompter.done.connect(Main::quit.slot()); + + Main::run(); + + if (prompter.status == Gtkmmext::Prompter::entered) { + string name; + + prompter.get_result(name); + + if (name.length()) { + if(plugin.save_preset(name)){ + combo.set_popdown_strings(plugin.get_presets()); + combo.get_entry()->set_text(name); + } + } + } +} + +void +PlugUIBase::bypass_toggled () +{ + bool x; + + if ((x = bypass_button.get_active()) == insert.active()) { + insert.set_active (!x, this); + } +} + diff --git a/gtk2_ardour/plugin_ui.h b/gtk2_ardour/plugin_ui.h new file mode 100644 index 0000000000..e46d7be9c0 --- /dev/null +++ b/gtk2_ardour/plugin_ui.h @@ -0,0 +1,230 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_plugin_ui_h__ +#define __ardour_plugin_ui_h__ + +#include +#include +#include + +#include + +#include +#include + +#include +#include + +namespace ARDOUR { + class AudioEngine; + class PluginInsert; + class Plugin; + class VSTPlugin; + class Redirect; +} + +namespace MIDI { + class Controllable; +} + +namespace Gtkmmext { + class HSliderController; + class BarController; + class ClickBox; + class FastMeter; + class PixmapButton; +} + +class PlugUIBase : public SigC::Object +{ + public: + PlugUIBase (ARDOUR::PluginInsert&); + virtual ~PlugUIBase() {} + + virtual gint get_preferred_height () = 0; + virtual gint start_updating(GdkEventAny*) = 0; + virtual gint stop_updating(GdkEventAny*) = 0; + + protected: + ARDOUR::PluginInsert& insert; + ARDOUR::Plugin& plugin; + Gtk::Combo combo; + Gtk::Button save_button; + Gtk::ToggleButton bypass_button; + + gint setting_selected(GdkEventAny* ignored); + void save_plugin_setting (void); + void bypass_toggled(); +}; + +class PluginUI : public PlugUIBase, public Gtk::VBox +{ + public: + PluginUI (ARDOUR::AudioEngine &, ARDOUR::PluginInsert& plug, bool scrollable=false); + ~PluginUI (); + + gint get_preferred_height () { return prefheight; } + + gint start_updating(GdkEventAny*); + gint stop_updating(GdkEventAny*); + + private: + ARDOUR::AudioEngine &engine; + Gtk::HBox settings_box; + Gtk::HBox hpacker; + Gtk::VBox info_vbox; + Gtk::EventBox name_ebox; + + Gtk::Table button_table; + Gtk::Table output_table; + + Gtk::ScrolledWindow scroller; + Gtk::Viewport scroller_view; + Gtk::Label nameinfo_label; + Gtk::Label paraminfo_label; + Gtk::Label makerinfo_label; + Gtk::Menu* automation_menu; + + bool setting_name_status; + + gint prefheight; + bool is_scrollable; + + struct MeterInfo { + Gtkmmext::FastMeter *meter; + + float min; + float max; + bool min_unbound; + bool max_unbound; + bool packed; + + MeterInfo(int i) { + meter = 0; + packed = false; + min = 1.0e10; + max = -1.0e10; + min_unbound = false; + max_unbound = false; + } + }; + + static const int32_t initial_button_rows = 6; + static const int32_t initial_button_cols = 1; + static const int32_t initial_output_rows = 8; + static const int32_t initial_output_cols = 1; + + struct ControlUI : public Gtk::HBox { + + uint32_t port_index; + + /* input */ + + Gtk::Adjustment* adjustment; + Gtk::Combo* combo; + std::map* combo_map; + Gtk::ToggleButton* button; + Gtkmmext::BarController* control; + Gtkmmext::ClickBox* clickbox; + Gtk::Label label; + bool logarithmic; + bool update_pending; + char ignore_change; + Gtk::Button automate_button; + + /* output */ + + Gtk::EventBox *display; + Gtk::Label* display_label; + + Gtk::VBox * vbox; + MeterInfo * meterinfo; + + ControlUI (); + ~ControlUI(); + }; + + std::vector output_controls; + SigC::Connection screen_update_connection; + void output_update(); + + void build (ARDOUR::AudioEngine &); + ControlUI* build_control_ui (ARDOUR::AudioEngine &, guint32 port_index, MIDI::Controllable *); + std::list setup_scale_values(guint32 port_index, ControlUI* cui); + void control_adjustment_changed (ControlUI* cui); + void parameter_changed (uint32_t, float, ControlUI* cui); + void update_control_display (ControlUI* cui); + void control_port_toggled (ControlUI* cui); + gint control_combo_changed (GdkEventAny* ignored, ControlUI* cui); + gint entry_focus_event (GdkEventFocus* ev); + + void redirect_active_changed (ARDOUR::Redirect*, void*); + + void astate_clicked (ControlUI*, uint32_t parameter); + void automation_state_changed (ControlUI*); + void set_automation_state (ARDOUR::AutoState state, ControlUI* cui); + void start_touch (ControlUI*); + void stop_touch (ControlUI*); + + void print_parameter (char *buf, uint32_t len, uint32_t param); +}; + +class PluginUIWindow : public ArdourDialog +{ + public: + PluginUIWindow (ARDOUR::AudioEngine &, ARDOUR::PluginInsert& insert, bool scrollable=false); + ~PluginUIWindow (); + + PlugUIBase& pluginui() { return *_pluginui; } + + void resize_preferred(); + + private: + PlugUIBase* _pluginui; + void plugin_going_away (ARDOUR::Redirect*); +}; + + +#ifdef VST_SUPPORT +class VSTPluginUI : public PlugUIBase, public Gtk::VBox +{ + public: + VSTPluginUI (ARDOUR::PluginInsert&, ARDOUR::VSTPlugin&); + ~VSTPluginUI (); + + gint get_preferred_height (); + gint start_updating(GdkEventAny*) { return 0; } + gint stop_updating(GdkEventAny*) { return 0; } + + int package (Gtk::Window&); + + private: + ARDOUR::VSTPlugin& vst; + Gtk::Socket socket; + Gtk::HBox preset_box; + Gtk::VBox vpacker; + + gboolean configure_handler (GdkEventConfigure*, GtkSocket*); + void save_plugin_setting (); +}; +#endif + +#endif /* __ardour_plugin_ui_h__ */ diff --git a/gtk2_ardour/po/.cvsignore b/gtk2_ardour/po/.cvsignore new file mode 100644 index 0000000000..3e8b787838 --- /dev/null +++ b/gtk2_ardour/po/.cvsignore @@ -0,0 +1,14 @@ +Makefile +Makefile.in +Makefile.in.in +POTFILES +Rules-quot +boldquot.sed +en@boldquot.header +en@quot.header +insert-header.sin +quot.sed +remove-potcdate.sin +remove-potcdate.sed +*.gmo +gtk-ardour.pot diff --git a/gtk2_ardour/po/de_DE.po b/gtk2_ardour/po/de_DE.po new file mode 100644 index 0000000000..7e464a775d --- /dev/null +++ b/gtk2_ardour/po/de_DE.po @@ -0,0 +1,5179 @@ +# German translations for gtk-ardour +# Copyright (C) 2003 Paul Davis +# This file is distributed under the same license as the gtk-ardour package. +# Karsten Petersen , 2003. +# +msgid "" +msgstr "" +"Project-Id-Version: gtk-ardour 0.347.2\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2005-09-19 18:09-0400\n" +"PO-Revision-Date: 2003-05-11 17:36+0200\n" +"Last-Translator: Karsten Petersen \n" +"Language-Team: Deutsch \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: KBabel 0.9.6\n" + +#: gtk_ardour/about.cc:134 +msgid "Marcus Andersson" +msgstr "" + +#: gtk_ardour/about.cc:135 +msgid "Jeremy Hall" +msgstr "" + +#: gtk_ardour/about.cc:136 +msgid "Steve Harris" +msgstr "" + +#: gtk_ardour/about.cc:137 +msgid "Tim Mayberry" +msgstr "" + +#: gtk_ardour/about.cc:138 +msgid "Mark Stewart" +msgstr "" + +#: gtk_ardour/about.cc:139 +msgid "Sam Chessman" +msgstr "" + +#: gtk_ardour/about.cc:140 +msgid "Jack O'Quin" +msgstr "" + +#: gtk_ardour/about.cc:141 +msgid "Matt Krai" +msgstr "" + +#: gtk_ardour/about.cc:142 +msgid "Ben Bell" +msgstr "" + +#: gtk_ardour/about.cc:143 +msgid "Gerard van Dongen" +msgstr "" + +#: gtk_ardour/about.cc:144 +msgid "Thomas Charbonnel" +msgstr "" + +#: gtk_ardour/about.cc:145 +msgid "Nick Mainsbridge" +msgstr "" + +#: gtk_ardour/about.cc:146 +msgid "Colin Law" +msgstr "" + +#: gtk_ardour/about.cc:147 +msgid "Sampo Savolainen" +msgstr "" + +#: gtk_ardour/about.cc:148 +msgid "Joshua Leach" +msgstr "" + +#: gtk_ardour/about.cc:149 +msgid "Rob Holland" +msgstr "" + +#: gtk_ardour/about.cc:150 +msgid "Per Sigmond" +msgstr "" + +#: gtk_ardour/about.cc:151 +msgid "Doug Mclain" +msgstr "" + +#: gtk_ardour/about.cc:156 +msgid "" +"French:\n" +"\tAlain Fréhel " +msgstr "" + +#: gtk_ardour/about.cc:157 +msgid "" +"German:\n" +"\tKarsten Petersen " +msgstr "" + +#: gtk_ardour/about.cc:158 +msgid "" +"Italian:\n" +"\tFilippo Pappalardo " +msgstr "" + +#: gtk_ardour/about.cc:159 +msgid "" +"Portuguese:\n" +"\tRui Nuno Capela " +msgstr "" + +#: gtk_ardour/about.cc:160 +msgid "" +"Brazilian Portuguese:\n" +"\tAlexander da Franca Fernandes \n" +"\tChris Ross " +msgstr "" + +#: gtk_ardour/about.cc:162 +msgid "" +"Spanish:\n" +"\t Alex Krohn " +msgstr "" + +#: gtk_ardour/about.cc:163 +msgid "" +"Russian:\n" +"\t Igor Blinov " +msgstr "" + +#: gtk_ardour/about.cc:181 +msgid "" +"Copyright (C) 1999-2005 Paul Davis\n" +"Ardour comes with ABSOLUTELY NO WARRANTY\n" +"This is free software, and you are welcome to redistribute it\n" +"under certain conditions; see the file COPYING for details.\n" +msgstr "" + +#: gtk_ardour/about.cc:188 +msgid "" +"Ardour: %1\n" +"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)" +msgstr "" + +#: gtk_ardour/about.cc:206 +msgid "" +"Primary author:\n" +"\tPaul Davis\n" +"\n" +"Major developers:\n" +"\tJesse Chappell\n" +"\tTaybin Rutkin\n" +"Contributors:\n" +"\t" +msgstr "" + +#: gtk_ardour/about.cc:243 +msgid "Authors" +msgstr "" + +#: gtk_ardour/about.cc:244 +#, fuzzy +msgid "Translators" +msgstr "dreieckig" + +#: gtk_ardour/about.cc:361 +msgid "cannot open splash image file \"%1\"" +msgstr "" + +#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33 +#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81 +#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977 +#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85 +#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777 +#: gtk_ardour/redirect_box.cc:900 +msgid "OK" +msgstr "" + +#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92 +#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046 +#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72 +#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982 +#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733 +#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000 +#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129 +#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785 +#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86 +#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072 +#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33 +#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161 +msgid "Cancel" +msgstr "Abbrechen" + +#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94 +msgid "Tracks" +msgstr "Spuren" + +#: gtk_ardour/add_route_dialog.cc:43 +msgid "Busses" +msgstr "" + +#: gtk_ardour/add_route_dialog.cc:48 +#, fuzzy +msgid "ardour: add track/bus" +msgstr "Ardour: Editor" + +#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81 +msgid "Add" +msgstr "Hinzufügen" + +#: gtk_ardour/add_route_dialog.cc:86 +#, fuzzy +msgid "Name (template)" +msgstr "Name für Mixer-Voreinstellung" + +#: gtk_ardour/ardour_ui.cc:798 +msgid "" +"pre\n" +"roll" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:799 +msgid "" +"post\n" +"roll" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:807 +msgid "% " +msgstr "" + +#: gtk_ardour/ardour_ui.cc:808 +#, fuzzy +msgid "spring" +msgstr "Importieren" + +#: gtk_ardour/ardour_ui.cc:810 +msgid "" +"punch\n" +"in" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:811 +msgid "" +"punch\n" +"out" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:812 +msgid "" +"auto\n" +"return" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:813 +msgid "" +"auto\n" +"play" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:814 +#, fuzzy +msgid "" +"auto\n" +"input" +msgstr "Port hinzufügen" + +#: gtk_ardour/ardour_ui.cc:815 +msgid "click" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:816 +msgid "" +"follow\n" +"PH" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:817 +msgid "AUDITIONING" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:818 +msgid "SOLO" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:870 +#, fuzzy +msgid "Percentage" +msgstr "Zurücksetzen" + +#: gtk_ardour/ardour_ui.cc:872 +#, fuzzy +msgid "Semitones" +msgstr "Sitzung" + +#: gtk_ardour/ardour_ui.cc:875 +#, fuzzy +msgid "Sprung" +msgstr "Sortieren" + +#: gtk_ardour/ardour_ui.cc:877 +msgid "Wheel" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:902 +msgid "" +"You cannot record-enable\n" +"track %1\n" +"because it has no input connections.\n" +"You would be wasting space recording silence." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1073 +msgid "quit" +msgstr "Verlassen" + +#: gtk_ardour/ardour_ui.cc:1082 +msgid "" +"Ardour was unable to save your session.\n" +"\n" +"If you still wish to quit, please use the\n" +"\n" +"\"Just quit\" option." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1107 +msgid "Save and %1" +msgstr "Speichern und %1" + +#: gtk_ardour/ardour_ui.cc:1112 +msgid "Just %1" +msgstr "Nur %1" + +#: gtk_ardour/ardour_ui.cc:1117 +msgid "Don't %1" +msgstr "Ohne %1" + +#: gtk_ardour/ardour_ui.cc:1126 +#, fuzzy +msgid "session" +msgstr "Sitzung" + +#: gtk_ardour/ardour_ui.cc:1128 +#, fuzzy +msgid "snapshot" +msgstr "Schnappschuß" + +#: gtk_ardour/ardour_ui.cc:1130 +#, fuzzy +msgid "" +"The %1\n" +"\"%2\"\n" +"has not been saved.\n" +"\n" +"Any changes made this time\n" +"will be lost unless you save it.\n" +"\n" +"What do you want to do?" +msgstr "" +"Die Sitzung \"%1\"\n" +"wurde nicht gespeichert.\n" +"\n" +"Alle Änderungen werden verloren\n" +"gehen wenn Sie nicht speichern.\n" +"\n" +"Was wollen Sie machen?" + +#: gtk_ardour/ardour_ui.cc:1151 +msgid "Prompter" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1152 +msgid "ardour: save session?" +msgstr "Ardour: Sitzung speichern?" + +#: gtk_ardour/ardour_ui.cc:1219 +#, fuzzy, c-format +msgid "disconnected" +msgstr "Trennen" + +#: gtk_ardour/ardour_ui.cc:1226 +#, c-format +msgid "SR: %.1f kHz / %4.1f msecs" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1230 +#, c-format +msgid "SR: %u kHz / %4.1f msecs" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1243 +#, fuzzy, c-format +msgid "DSP Load: %.1f%%" +msgstr "Auslastung der CPU: %.1f%%" + +#: gtk_ardour/ardour_ui.cc:1253 +#, c-format +msgid "Disk r:%5.1f w:%5.1f MB/s" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1267 +#, c-format +msgid "Buffers p:%%% c:%%%" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1294 +msgid "space: 24hrs+" +msgstr "Platz: >24 Stunden" + +#: gtk_ardour/ardour_ui.cc:1324 +#, c-format +msgid "space: %02dh:%02dm:%02ds" +msgstr "Platz: %02dh:%02dm:%02ds" + +#: gtk_ardour/ardour_ui.cc:1575 +msgid "programming error: impossible control method" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1800 +msgid "cancel" +msgstr "Abbrechen" + +#: gtk_ardour/ardour_ui.cc:1801 +msgid "rescan" +msgstr "Auffrischen" + +#: gtk_ardour/ardour_ui.cc:1842 +#, fuzzy +msgid "open session" +msgstr "Sitzung" + +#: gtk_ardour/ardour_ui.cc:1897 +msgid "Patience is a virtue.\n" +msgstr "Geduld ist eine Tugend.\n" + +#: gtk_ardour/ardour_ui.cc:1906 +msgid "You cannot add a track without a session already loaded." +msgstr "Sie können erst eine Spur hinzufügen, wenn eine Sitzung geladen wurde." + +#: gtk_ardour/ardour_ui.cc:1913 +msgid "could not create new audio track" +msgstr "Konnte neue Spur nicht erstellen." + +#: gtk_ardour/ardour_ui.cc:1917 +msgid "could not create new audio bus" +msgstr "Konnte neuen Audiokanal nicht erstellen." + +#: gtk_ardour/ardour_ui.cc:1936 +msgid "" +"There are insufficient JACK ports available\n" +"to create a new track or bus.\n" +"You should save Ardour, exit and\n" +"restart JACK with more ports." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2071 +msgid "" +"Please create 1 or more track\n" +"before trying to record.\n" +"Check the Session menu." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2312 +#, fuzzy +msgid "" +"JACK has either been shutdown or it\n" +"disconnected Ardour because Ardour\n" +"was not fast enough. You can save the\n" +"session and/or try to reconnect to JACK ." +msgstr "" +"JACK wurde entweder beendet oder es\n" +"hat Ardour abgekoppelt weil Ardour nicht\n" +"schnell genug war. Sie sollten die Sitzung\n" +"speichern und JACK sowie Ardour neu starten." + +#: gtk_ardour/ardour_ui.cc:2328 +msgid "Unable to create all required ports" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2336 +#, fuzzy +msgid "Unable to start the session running" +msgstr "An den Anfang der Sitzung springen" + +#: gtk_ardour/ardour_ui.cc:2472 +msgid "No Stream" +msgstr "Kein Datenstrom" + +#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518 +msgid "none" +msgstr "keine" + +#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527 +#: gtk_ardour/automation_time_axis.cc:189 +#: gtk_ardour/automation_time_axis.cc:218 +#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211 +#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947 +#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659 +msgid "off" +msgstr "aus" + +#: gtk_ardour/ardour_ui.cc:2548 +msgid "Name for snapshot" +msgstr "Name für Schnappschuß" + +#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294 +msgid "Name for mix template:" +msgstr "Name für Mixer-Voreinstellung" + +#: gtk_ardour/ardour_ui.cc:2717 +#, fuzzy +msgid "-template" +msgstr "Voreinstellung" + +#: gtk_ardour/ardour_ui.cc:2760 +msgid "Session %1 already exists at %2" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2832 +msgid "" +"You do not have write access to this session.\n" +"This prevents the session from being loaded." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897 +#, fuzzy +msgid "Session \"%1 (snapshot %2)\" did not load successfully" +msgstr "Sitzung \"%1\" konnte nicht geladen werden." + +#: gtk_ardour/ardour_ui.cc:2966 +msgid "" +"No audio files were ready for cleanup\n" +"\n" +"If this seems suprising, check for any existing\n" +"snapshots. These may still include regions that\n" +"require some unused files to continue to exist." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001 +msgid "files" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003 +msgid "file" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3026 +#, fuzzy +msgid "ardour: cleanup" +msgstr "Ardour: Uhr" + +#: gtk_ardour/ardour_ui.cc:3040 +msgid "" +"Cleanup is a destructive operation.\n" +"ALL undo/redo information will be lost if you cleanup.\n" +"Unused audio files will be moved to a \"dead sounds\" location." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3045 +msgid "Proceed with cleanup" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3061 +#, fuzzy +msgid "CleanupDialog" +msgstr "leeren" + +#: gtk_ardour/ardour_ui.cc:3062 +#, fuzzy +msgid "ardour cleanup" +msgstr "Ardour: Uhr" + +#: gtk_ardour/ardour_ui.cc:3063 +#, fuzzy +msgid "ardour_cleanup" +msgstr "Ardour: Uhr" + +#: gtk_ardour/ardour_ui.cc:3086 +msgid "cleaned files" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3087 +msgid "" +"The following %1 %2 were not in use.\n" +"The next time you flush the wastebasket\n" +"it will release an additional %3 %4bytes\n" +"of disk space" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3110 +#, fuzzy +msgid "deleted file" +msgstr "entfernen" + +#: gtk_ardour/ardour_ui.cc:3111 +msgid "" +"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3226 +msgid "Recording was stopped because your system could not keep up." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3248 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to write data to disk\n" +"quickly enough to keep up with recording.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3266 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to read data from disk\n" +"quickly enough to keep up with playback.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3291 +msgid "Recover from crash" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3292 +msgid "Ignore crash data" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3293 +msgid "" +"This session appears to have been in\n" +"middle of recording when ardour or\n" +"the computer was shutdown.\n" +"\n" +"Ardour can recover any captured audio for\n" +"you, or it can ignore it. Please decide\n" +"what you would like to do.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3338 +msgid "Could not disconnect from JACK" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3351 +msgid "Could not reconnect to JACK" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:60 +msgid "UI: cannot setup editor" +msgstr "Der Editor konnte nicht initialisiert werden." + +#: gtk_ardour/ardour_ui2.cc:65 +msgid "UI: cannot setup mixer" +msgstr "Der Mixer konnte nicht initialisiert werden." + +#: gtk_ardour/ardour_ui2.cc:70 +msgid "UI: cannot setup meter_bridge" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:98 +msgid "MMC + Local" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:99 +msgid "MMC" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:100 +msgid "Local" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:117 +msgid "MMC ID" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:215 +msgid "Play from playhead" +msgstr "Wiedergabe ab Playhead" + +#: gtk_ardour/ardour_ui2.cc:216 +msgid "Stop playback" +msgstr "Wiedergabe anhalten" + +#: gtk_ardour/ardour_ui2.cc:217 +#, fuzzy +msgid "Play range/selection" +msgstr "Auswahl wiedergeben" + +#: gtk_ardour/ardour_ui2.cc:218 +msgid "Go to start of session" +msgstr "An den Anfang der Sitzung springen" + +#: gtk_ardour/ardour_ui2.cc:219 +msgid "Go to end of session" +msgstr "Ans Ende der Sitzung springen" + +#: gtk_ardour/ardour_ui2.cc:220 +#, fuzzy +msgid "Play loop range" +msgstr "Bereich" + +#: gtk_ardour/ardour_ui2.cc:221 +msgid "Return to last playback start when stopped" +msgstr "Bei Stopp zum Wiedergabeanfang springen" + +#: gtk_ardour/ardour_ui2.cc:222 +msgid "Start playback after any locate" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:223 +msgid "Be sensible about input monitoring" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:224 +msgid "Start recording at auto-punch start" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:225 +msgid "Stop recording at auto-punch end" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:226 +msgid "Enable/Disable audio click" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:227 +#, fuzzy +msgid "Enable/Disable follow playhead" +msgstr "Wiedergabeschleife an/abschalten" + +#: gtk_ardour/ardour_ui2.cc:228 +msgid "Shuttle speed control" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:229 +#, c-format +msgid "Select semitones or %%-age for speed display" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:230 +msgid "Select sprung or wheel behaviour" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:231 +msgid "Current transport speed" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:312 +#, fuzzy +msgid "Primary clock" +msgstr "Ardour: Uhr" + +#: gtk_ardour/ardour_ui2.cc:313 +msgid "secondary clock" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751 +#: gtk_ardour/ardour_ui2.cc:770 +msgid "stopped" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:431 +msgid "ardour: clock" +msgstr "Ardour: Uhr" + +#: gtk_ardour/ardour_ui2.cc:721 +#, fuzzy +msgid "st" +msgstr "bestmöglich" + +#: gtk_ardour/ardour_ui2.cc:731 +msgid "sprung" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:742 +msgid "wheel" +msgstr "" + +#: gtk_ardour/ardour_ui_dependents.cc:74 +msgid "keyboard_target: error setting binding state: invalid node" +msgstr "" + +#: gtk_ardour/ardour_ui_dialogs.cc:158 +#, fuzzy +msgid "close session" +msgstr "Bitte mittels des \"Sitzung\"-Menüs\n" + +#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895 +#, fuzzy +msgid "New" +msgstr "Neu..." + +#: gtk_ardour/ardour_ui_ed.cc:76 +#, fuzzy +msgid "Open" +msgstr "Öffnen..." + +#: gtk_ardour/ardour_ui_ed.cc:77 +#, fuzzy +msgid "Recent" +msgstr "Zurücksetzen" + +#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +msgid "Close" +msgstr "Schließen" + +#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488 +#, fuzzy +msgid "Add Track/Bus" +msgstr "MIDI Spur(en) hinzufügen" + +#: gtk_ardour/ardour_ui_ed.cc:99 +#, fuzzy +msgid "Connect" +msgstr "Verbindungen" + +#: gtk_ardour/ardour_ui_ed.cc:100 +msgid "Image Compositor" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:114 +msgid "Save" +msgstr "Speichern" + +#: gtk_ardour/ardour_ui_ed.cc:118 +msgid "Snapshot" +msgstr "Schnappschuß" + +#: gtk_ardour/ardour_ui_ed.cc:126 +msgid "Save Template..." +msgstr "Speichern als Voreinstellung..." + +#: gtk_ardour/ardour_ui_ed.cc:133 +msgid "Export session to audiofile..." +msgstr "Export als Audio-Datei..." + +#: gtk_ardour/ardour_ui_ed.cc:134 +#, fuzzy +msgid "Export range to audiofile..." +msgstr "Export als Audio-Datei..." + +#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312 +#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118 +#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227 +msgid "Export" +msgstr "Exportieren" + +#: gtk_ardour/ardour_ui_ed.cc:146 +msgid "Cleanup unused sources" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:147 +msgid "Flush wastebasket" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:149 +#, fuzzy +msgid "Cleanup" +msgstr "leeren" + +#: gtk_ardour/ardour_ui_ed.cc:154 +msgid "Quit" +msgstr "Beenden" + +#: gtk_ardour/ardour_ui_ed.cc:156 +msgid "Session" +msgstr "Sitzung" + +#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287 +#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499 +#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570 +#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412 +msgid "Edit" +msgstr "Bearbeiten" + +#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572 +#: gtk_ardour/mixer_strip.cc:631 +msgid "Disconnect" +msgstr "Trennen" + +#: gtk_ardour/ardour_ui_ed.cc:174 +#, fuzzy +msgid "Reconnect" +msgstr "Verbindungen" + +#: gtk_ardour/ardour_ui_ed.cc:192 +msgid "Latency" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:195 +msgid "JACK" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:205 +msgid "Editor" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:206 +msgid "Mixer" +msgstr "Mixer" + +#: gtk_ardour/ardour_ui_ed.cc:212 +#, fuzzy +msgid "Options Editor" +msgstr "Geschwindigkeitseditor" + +#: gtk_ardour/ardour_ui_ed.cc:219 +#, fuzzy +msgid "Audio Library" +msgstr "Ardour: Audio Bibliothek" + +#: gtk_ardour/ardour_ui_ed.cc:225 +msgid "Track/Bus Inspector" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:232 +msgid "Connections" +msgstr "Verbindungen" + +#: gtk_ardour/ardour_ui_ed.cc:240 +msgid "Meter Bridge" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:248 +msgid "Locations" +msgstr "Stellen" + +#: gtk_ardour/ardour_ui_ed.cc:255 +msgid "Big Clock" +msgstr "Große Uhr" + +#: gtk_ardour/ardour_ui_ed.cc:261 +msgid "About" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:264 +msgid "Windows" +msgstr "Fenster" + +#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203 +msgid "SMPTE" +msgstr "" + +#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202 +#: gtk_ardour/editor_rulers.cc:359 +msgid "Bars:Beats" +msgstr "" + +#: gtk_ardour/audio_clock.cc:1642 +msgid "Minutes:Seconds" +msgstr "Minuten:Sekunden" + +#: gtk_ardour/audio_clock.cc:1643 +msgid "Audio Frames" +msgstr "" + +#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356 +#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713 +#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774 +#: gtk_ardour/option_editor.cc:794 +msgid "Off" +msgstr "Aus" + +#: gtk_ardour/audio_clock.cc:1646 +msgid "Mode" +msgstr "Modus" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523 +msgid "m" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524 +msgid "s" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:104 +msgid "r" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:108 +msgid "g" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:109 +msgid "p" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44 +#: gtk_ardour/visual_time_axis.cc:90 +msgid "h" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:111 +msgid "a" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89 +msgid "v" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:185 +#, fuzzy +msgid "Record" +msgstr "Wiederherstellen" + +#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191 +#, fuzzy +msgid "Solo" +msgstr "solo" + +#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236 +#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433 +#, fuzzy +msgid "Mute" +msgstr "mute" + +#: gtk_ardour/audio_time_axis.cc:188 +#, fuzzy +msgid "Edit Group" +msgstr "Mix Gruppen" + +#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110 +#, fuzzy +msgid "Display Height" +msgstr "Anzeige" + +#: gtk_ardour/audio_time_axis.cc:190 +#, fuzzy +msgid "Playlist" +msgstr "Wiedergabe" + +#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752 +#, fuzzy +msgid "Automation" +msgstr "Stellen" + +#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111 +msgid "Visual options" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112 +msgid "Hide this track" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:349 +#, fuzzy +msgid "No group" +msgstr "keine Gruppe" + +#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447 +#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229 +#, fuzzy +msgid "Height" +msgstr "Rechts" + +#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266 +#: gtk_ardour/marker_time_axis.cc:230 +#, fuzzy +msgid "Color" +msgstr "solo" + +#: gtk_ardour/audio_time_axis.cc:720 +msgid "Hide all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:721 +msgid "Show all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:729 +#, fuzzy +msgid "show all automation" +msgstr "Stellen" + +#: gtk_ardour/audio_time_axis.cc:732 +#, fuzzy +msgid "show existing automation" +msgstr "Stellen" + +#: gtk_ardour/audio_time_axis.cc:735 +#, fuzzy +msgid "hide all automation" +msgstr "Stellen" + +#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204 +#: gtk_ardour/editor.cc:234 +msgid "gain" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244 +msgid "pan" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388 +msgid "Plugins" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95 +#, fuzzy +msgid "Show waveforms" +msgstr "Wellenform zeigen" + +#: gtk_ardour/audio_time_axis.cc:766 +msgid "Traditional" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:769 +msgid "Rectified" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:772 +#, fuzzy +msgid "Waveform" +msgstr "Wellenform zeigen" + +#: gtk_ardour/audio_time_axis.cc:782 +msgid "align with existing material" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:787 +msgid "align with capture time" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:793 +msgid "Alignment" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288 +msgid "Active" +msgstr "Aktiv" + +#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386 +#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467 +#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269 +#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233 +#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83 +msgid "Remove" +msgstr "Entfernen" + +#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880 +#: gtk_ardour/audio_time_axis.cc:911 +#, fuzzy +msgid "Name for playlist" +msgstr "Name für Schnappschuß" + +#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433 +msgid "a track already exists with that name" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001 +#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539 +msgid "programming error: " +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:1889 +msgid "Current: %1" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452 +#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226 +#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377 +msgid "Rename" +msgstr "Umbenennen" + +#: gtk_ardour/audio_time_axis.cc:1896 +#, fuzzy +msgid "New Copy" +msgstr "Kopieren" + +#: gtk_ardour/audio_time_axis.cc:1898 +msgid "Clear Current" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472 +#: gtk_ardour/editor.cc:2557 +msgid "Select" +msgstr "Auswahl" + +#: gtk_ardour/automation_line.cc:904 +#, fuzzy +msgid "automation event move" +msgstr "Stellen" + +#: gtk_ardour/automation_line.cc:906 +#, fuzzy +msgid "automation range drag" +msgstr "Stellen" + +#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64 +#, fuzzy +msgid "remove control point" +msgstr "Synchronisationspunkt entfernen" + +#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010 +msgid "clear" +msgstr "leeren" + +#: gtk_ardour/automation_time_axis.cc:80 +msgid "track height" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:81 +#, fuzzy +msgid "automation state" +msgstr "Stellen" + +#: gtk_ardour/automation_time_axis.cc:82 +#, fuzzy +msgid "clear track" +msgstr "Verbindungen löschen" + +#: gtk_ardour/automation_time_axis.cc:83 +#, fuzzy +msgid "hide track" +msgstr "Stille einfügen" + +#: gtk_ardour/automation_time_axis.cc:191 +#: gtk_ardour/automation_time_axis.cc:229 +#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213 +#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419 +#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50 +msgid "play" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:193 +#: gtk_ardour/automation_time_axis.cc:240 +#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215 +#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422 +#: gtk_ardour/plugin_ui.cc:663 +msgid "write" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:195 +#: gtk_ardour/automation_time_axis.cc:251 +#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217 +#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953 +#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665 +msgid "touch" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274 +#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428 +msgid "???" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:276 +#, fuzzy +msgid "clear automation" +msgstr "Verbindungen löschen" + +#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453 +#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398 +msgid "Hide" +msgstr "Verbergen" + +#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52 +#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364 +msgid "Clear" +msgstr "leeren" + +#: gtk_ardour/automation_time_axis.cc:474 +#, fuzzy +msgid "State" +msgstr "Anfang" + +#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49 +msgid "Input Connections" +msgstr "Verbindungen der Eingänge" + +#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48 +msgid "Output Connections" +msgstr "Verbindungen der Ausgänge" + +#: gtk_ardour/connection_editor.cc:49 +#, fuzzy +msgid "New Input" +msgstr "Neuer Eingang" + +#: gtk_ardour/connection_editor.cc:50 +#, fuzzy +msgid "New Output" +msgstr "Neuer Ausgang" + +#: gtk_ardour/connection_editor.cc:51 +#, fuzzy +msgid "Delete" +msgstr "entfernen" + +#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96 +#, fuzzy +msgid "Add Port" +msgstr "Port hinzufügen" + +#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105 +#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786 +#, fuzzy +msgid "Rescan" +msgstr "Auffrischen" + +#: gtk_ardour/connection_editor.cc:101 +#, fuzzy +msgid "Available Ports" +msgstr "Verfügbare Verbindungen" + +#: gtk_ardour/connection_editor.cc:183 +msgid "ardour: connections" +msgstr "Ardour: Verbindungen" + +#: gtk_ardour/connection_editor.cc:513 +#, c-format +msgid "in %d" +msgstr "" + +#: gtk_ardour/connection_editor.cc:644 +msgid "Name for new connection:" +msgstr "Name für neue Verbindung:" + +#: gtk_ardour/crossfade_edit.cc:71 +#, fuzzy +msgid "crossfade editor" +msgstr "Ardour: Editor" + +#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449 +#, fuzzy +msgid "Reset" +msgstr "bestmöglich" + +#: gtk_ardour/crossfade_edit.cc:78 +msgid "Fade" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:79 +msgid "Out (dry)" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:80 +#, fuzzy +msgid "Out" +msgstr "Ausgänge" + +#: gtk_ardour/crossfade_edit.cc:81 +msgid "In (dry)" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:82 +msgid "In" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:84 +msgid "With Pre-roll" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:85 +msgid "With Post-roll" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:93 +msgid "Fade In" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:94 +msgid "Fade Out" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:98 +#, fuzzy +msgid "ardour: x-fade edit" +msgstr "Ardour: Editor" + +#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311 +#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189 +msgid "Audition" +msgstr "" + +#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804 +#, fuzzy +msgid "Regions/name" +msgstr "Regionen" + +#: gtk_ardour/editor.cc:108 +msgid "Chunks" +msgstr "Stücke" + +#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079 +msgid "Slide" +msgstr "" + +#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077 +msgid "Splice" +msgstr "" + +#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136 +#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96 +#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977 +msgid "None" +msgstr "Nichts" + +#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124 +msgid "CD Frames" +msgstr "" + +#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126 +msgid "SMPTE Frames" +msgstr "" + +#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128 +msgid "SMPTE Seconds" +msgstr "" + +#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130 +msgid "SMPTE Minutes" +msgstr "" + +#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132 +#, fuzzy +msgid "Seconds" +msgstr "Minuten:Sekunden" + +#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134 +#, fuzzy +msgid "Minutes" +msgstr "mute" + +#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106 +msgid "Beats/32" +msgstr "" + +#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104 +msgid "Beats/16" +msgstr "" + +#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102 +msgid "Beats/8" +msgstr "" + +#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100 +msgid "Beats/4" +msgstr "" + +#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098 +msgid "Beats/3" +msgstr "" + +#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108 +msgid "Beats" +msgstr "" + +#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110 +msgid "Bars" +msgstr "" + +#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112 +msgid "Marks" +msgstr "" + +#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114 +#: gtk_ardour/editor.cc:4182 +msgid "Edit Cursor" +msgstr "" + +#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116 +#, fuzzy +msgid "Region starts" +msgstr "Regionen" + +#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118 +#, fuzzy +msgid "Region ends" +msgstr "Regionen" + +#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122 +#, fuzzy +msgid "Region syncs" +msgstr "Regionen" + +#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120 +#, fuzzy +msgid "Region bounds" +msgstr "Regionen" + +#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153 +#: gtk_ardour/time_axis_view.cc:449 +msgid "Normal" +msgstr "" + +#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155 +#, fuzzy +msgid "Magnetic" +msgstr "generisch" + +#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174 +#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237 +msgid "Left" +msgstr "Links" + +#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176 +#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238 +msgid "Right" +msgstr "Rechts" + +#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178 +msgid "Center" +msgstr "Mitte" + +#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180 +msgid "Playhead" +msgstr "" + +#: gtk_ardour/editor.cc:201 +msgid "Mins:Secs" +msgstr "Min:Sek" + +#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353 +msgid "Frames" +msgstr "" + +#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373 +msgid "Tempo" +msgstr "" + +#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367 +msgid "Meter" +msgstr "" + +#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379 +#, fuzzy +msgid "Location Markers" +msgstr "Stellen" + +#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385 +msgid "Range Markers" +msgstr "" + +#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391 +msgid "Loop/Punch Ranges" +msgstr "" + +#: gtk_ardour/editor.cc:221 +#, fuzzy +msgid "" +"editor\n" +"mixer" +msgstr "Ardour: Mixer" + +#: gtk_ardour/editor.cc:232 +msgid "range" +msgstr "Bereich" + +#: gtk_ardour/editor.cc:233 +msgid "object" +msgstr "Objekt" + +#: gtk_ardour/editor.cc:235 +msgid "zoom" +msgstr "" + +#: gtk_ardour/editor.cc:236 +msgid "timefx" +msgstr "" + +#: gtk_ardour/editor.cc:237 +msgid "listen" +msgstr "" + +#: gtk_ardour/editor.cc:239 +msgid "mode" +msgstr "Modus" + +#: gtk_ardour/editor.cc:240 +msgid "automation" +msgstr "" + +#: gtk_ardour/editor.cc:242 +msgid "Edit Mode" +msgstr "Bearbeitungs Modus" + +#: gtk_ardour/editor.cc:243 +msgid "Snap To" +msgstr "" + +#: gtk_ardour/editor.cc:244 +#, fuzzy +msgid "Snap Mode" +msgstr "Modus" + +#: gtk_ardour/editor.cc:245 +#, fuzzy +msgid "Zoom Focus" +msgstr "Verkleinern" + +#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364 +#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579 +msgid "Nudge" +msgstr "" + +#: gtk_ardour/editor.cc:511 +msgid "Zoom in" +msgstr "Vergrößern" + +#: gtk_ardour/editor.cc:512 +msgid "Zoom out" +msgstr "Verkleinern" + +#: gtk_ardour/editor.cc:517 +#, fuzzy +msgid "Zoom to session" +msgstr "Vergrößern auf Auswahl" + +#: gtk_ardour/editor.cc:536 +#, fuzzy +msgid "Zoom Span" +msgstr "Vergrößern" + +#: gtk_ardour/editor.cc:566 +msgid "Edit Groups" +msgstr "" + +#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142 +msgid "-all-" +msgstr "-alle-" + +#: gtk_ardour/editor.cc:718 +msgid "Nudge region/selection forwards" +msgstr "" + +#: gtk_ardour/editor.cc:719 +msgid "Nudge region/selection backwards" +msgstr "" + +#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308 +msgid "ardour: editor" +msgstr "Ardour: Editor" + +#: gtk_ardour/editor.cc:729 +#, fuzzy +msgid "ardour_editor" +msgstr "Ardour: Editor" + +#: gtk_ardour/editor.cc:846 +msgid "VerboseCanvasCursor" +msgstr "" + +#: gtk_ardour/editor.cc:1405 +msgid "FirstActionMessage" +msgstr "" + +#: gtk_ardour/editor.cc:1407 +#, fuzzy +msgid "Start a new session\n" +msgstr "Bitte mittels des \"Sitzung\"-Menüs\n" + +#: gtk_ardour/editor.cc:1408 +msgid "via Session menu" +msgstr "eine Sitzung laden oder eine neue erstellen!" + +#: gtk_ardour/editor.cc:1703 +msgid "ardour: editor: " +msgstr "Ardour: Editor: " + +#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796 +#: gtk_ardour/editor_markers.cc:797 +msgid "Loop" +msgstr "Schleife" + +#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810 +#: gtk_ardour/editor_markers.cc:823 +msgid "Punch" +msgstr "" + +#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688 +msgid "programming error: fade in canvas item has no regionview data pointer!" +msgstr "" + +#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986 +#: gtk_ardour/redirect_box.cc:401 +#, fuzzy +msgid "Deactivate" +msgstr "Alles deaktivieren" + +#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988 +#: gtk_ardour/redirect_box.cc:398 +#, fuzzy +msgid "Activate" +msgstr "Aktiv" + +#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993 +msgid "Linear" +msgstr "" + +#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994 +#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734 +#: gtk_ardour/option_editor.cc:796 +#, fuzzy +msgid "Slowest" +msgstr "Alle zeigen" + +#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995 +#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735 +#: gtk_ardour/option_editor.cc:798 +#, fuzzy +msgid "Slow" +msgstr "solo" + +#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996 +#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737 +#: gtk_ardour/option_editor.cc:802 +#, fuzzy +msgid "Fast" +msgstr "Einfügen" + +#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997 +#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739 +#: gtk_ardour/option_editor.cc:806 +#, fuzzy +msgid "Fastest" +msgstr "schnellstmöglich" + +#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113 +msgid "Freeze" +msgstr "" + +#: gtk_ardour/editor.cc:2109 +msgid "Unfreeze" +msgstr "" + +#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328 +#, fuzzy +msgid "Unmute" +msgstr "mute" + +#: gtk_ardour/editor.cc:2247 +msgid "Convert to short" +msgstr "" + +#: gtk_ardour/editor.cc:2249 +msgid "Convert to full" +msgstr "" + +#: gtk_ardour/editor.cc:2260 +#, fuzzy +msgid "Crossfade" +msgstr "Ardour: Editor" + +#: gtk_ardour/editor.cc:2303 +msgid "Popup region editor" +msgstr "Regionen Editor öffnen" + +#: gtk_ardour/editor.cc:2304 +#, fuzzy +msgid "Raise to top layer" +msgstr "Region ganz nach oben" + +#: gtk_ardour/editor.cc:2305 +#, fuzzy +msgid "Lower to bottom layer" +msgstr "Region ganz nach unten" + +#: gtk_ardour/editor.cc:2307 +msgid "Define sync point" +msgstr "Synchronisationspunkt definieren" + +#: gtk_ardour/editor.cc:2308 +msgid "Remove sync point" +msgstr "Synchronisationspunkt entfernen" + +#: gtk_ardour/editor.cc:2313 +#, fuzzy +msgid "Bounce" +msgstr "Bereich" + +#: gtk_ardour/editor.cc:2323 +#, fuzzy +msgid "Lock" +msgstr "OK" + +#: gtk_ardour/editor.cc:2324 +#, fuzzy +msgid "Unlock" +msgstr "Rückgängig" + +#: gtk_ardour/editor.cc:2334 +#, fuzzy +msgid "Original position" +msgstr "Regionen" + +#: gtk_ardour/editor.cc:2340 +msgid "Toggle envelope visibility" +msgstr "" + +#: gtk_ardour/editor.cc:2341 +msgid "Toggle envelope active" +msgstr "" + +#: gtk_ardour/editor.cc:2345 +#, fuzzy +msgid "DeNormalize" +msgstr "Ardour: Region" + +#: gtk_ardour/editor.cc:2347 +#, fuzzy +msgid "Normalize" +msgstr "Ardour: Region" + +#: gtk_ardour/editor.cc:2350 +#, fuzzy +msgid "Reverse" +msgstr "Entfernen" + +#: gtk_ardour/editor.cc:2359 +msgid "Nudge fwd" +msgstr "" + +#: gtk_ardour/editor.cc:2360 +msgid "Nudge bwd" +msgstr "" + +#: gtk_ardour/editor.cc:2361 +msgid "Nudge fwd by capture offset" +msgstr "" + +#: gtk_ardour/editor.cc:2362 +msgid "Nudge bwd by capture offset" +msgstr "" + +#: gtk_ardour/editor.cc:2371 +msgid "Start to edit cursor" +msgstr "" + +#: gtk_ardour/editor.cc:2372 +msgid "Edit cursor to end" +msgstr "" + +#: gtk_ardour/editor.cc:2374 +msgid "Trim" +msgstr "" + +#: gtk_ardour/editor.cc:2377 +msgid "Split" +msgstr "Teilen" + +#: gtk_ardour/editor.cc:2380 +#, fuzzy +msgid "Make mono regions" +msgstr "Name für Region:" + +#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428 +msgid "Duplicate" +msgstr "Duplizieren" + +#: gtk_ardour/editor.cc:2384 +#, fuzzy +msgid "Fill Track" +msgstr "Spur" + +#: gtk_ardour/editor.cc:2388 +msgid "Destroy" +msgstr "" + +#: gtk_ardour/editor.cc:2418 +#, fuzzy +msgid "Play range" +msgstr "Bereich" + +#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446 +#, fuzzy +msgid "Loop range" +msgstr "Bereich" + +#: gtk_ardour/editor.cc:2421 +#, fuzzy +msgid "Create chunk from range" +msgstr "Auswahl zu Abschnitt machen" + +#: gtk_ardour/editor.cc:2423 +msgid "Create Region" +msgstr "Region erstellen" + +#: gtk_ardour/editor.cc:2424 +msgid "Separate Region" +msgstr "" + +#: gtk_ardour/editor.cc:2425 +#, fuzzy +msgid "Crop Region to range" +msgstr "Regionen Editor öffnen" + +#: gtk_ardour/editor.cc:2426 +#, fuzzy +msgid "Bounce range" +msgstr "Bereich" + +#: gtk_ardour/editor.cc:2432 +#, fuzzy +msgid "Fill range w/Region" +msgstr "Region erstellen" + +#: gtk_ardour/editor.cc:2434 +#, fuzzy +msgid "Range" +msgstr "Bereich" + +#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538 +#, fuzzy +msgid "Play from edit cursor" +msgstr "Wiedergabe ab Cursor" + +#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539 +msgid "Play from start" +msgstr "Wiedergabe ab Anfang" + +#: gtk_ardour/editor.cc:2451 +#, fuzzy +msgid "Play region" +msgstr "Wiedergabe der Region" + +#: gtk_ardour/editor.cc:2453 +#, fuzzy +msgid "Loop Region" +msgstr "Auswahl zu Schleife machen" + +#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540 +#: gtk_ardour/library_ui.cc:972 +msgid "Play" +msgstr "Wiedergabe" + +#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548 +#, fuzzy +msgid "Select All in track" +msgstr "Auswahl" + +#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549 +#, fuzzy +msgid "Select All" +msgstr "Auswahl" + +#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550 +#, fuzzy +msgid "Invert in track" +msgstr "Stille einfügen" + +#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551 +msgid "Invert" +msgstr "" + +#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553 +#, fuzzy +msgid "Select loop range" +msgstr "Ausgewählten Bereich wiedergeben" + +#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554 +#, fuzzy +msgid "Select punch range" +msgstr "Ausgewählten Bereich wiedergeben" + +#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565 +#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369 +msgid "Cut" +msgstr "Ausschneiden" + +#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566 +#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371 +msgid "Copy" +msgstr "Kopieren" + +#: gtk_ardour/editor.cc:2482 +#, fuzzy +msgid "Paste at edit cursor" +msgstr "Wiedergabe ab Cursor" + +#: gtk_ardour/editor.cc:2483 +msgid "Paste at mouse" +msgstr "" + +#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923 +msgid "Align" +msgstr "" + +#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925 +msgid "Align Relative" +msgstr "" + +#: gtk_ardour/editor.cc:2492 +msgid "Insert chunk" +msgstr "Abschnitt einfügen" + +#: gtk_ardour/editor.cc:2496 +msgid "New Region from range" +msgstr "" + +#: gtk_ardour/editor.cc:2497 +#, fuzzy +msgid "Separate Range" +msgstr "Ausgewählten Bereich wiedergeben" + +#: gtk_ardour/editor.cc:2507 +msgid "Insert Region" +msgstr "" + +#: gtk_ardour/editor.cc:2508 +msgid "Insert external sndfile" +msgstr "" + +#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438 +msgid "Import" +msgstr "Importieren" + +#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574 +msgid "Nudge entire track fwd" +msgstr "" + +#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575 +msgid "Nudge track after edit cursor fwd" +msgstr "" + +#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576 +msgid "Nudge entire track bwd" +msgstr "" + +#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577 +msgid "Nudge track after edit cursor bwd" +msgstr "" + +#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920 +#: gtk_ardour/redirect_box.cc:373 +msgid "Paste" +msgstr "Einfügen" + +#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645 +#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799 +msgid "add marker" +msgstr "" + +#: gtk_ardour/editor.cc:3084 +msgid "select/move objects" +msgstr "" + +#: gtk_ardour/editor.cc:3085 +#, fuzzy +msgid "select/move ranges" +msgstr "Ausgewählten Bereich wiedergeben" + +#: gtk_ardour/editor.cc:3086 +msgid "draw gain automation" +msgstr "" + +#: gtk_ardour/editor.cc:3087 +#, fuzzy +msgid "select zoom range" +msgstr "Ausgewählten Bereich wiedergeben" + +#: gtk_ardour/editor.cc:3088 +msgid "stretch/shrink regions" +msgstr "" + +#: gtk_ardour/editor.cc:3089 +#, fuzzy +msgid "listen to specific regions" +msgstr "Auswahl zu Schleife machen" + +#: gtk_ardour/editor.cc:3213 +msgid "Start:" +msgstr "Anfang:" + +#: gtk_ardour/editor.cc:3214 +msgid "End:" +msgstr "Ende:" + +#: gtk_ardour/editor.cc:3215 +msgid "Edit:" +msgstr "Bearbeiten:" + +#: gtk_ardour/editor.cc:3429 +msgid "incorrectly formatted URI list, ignored" +msgstr "" + +#: gtk_ardour/editor.cc:3611 +#, fuzzy +msgid "set selected trackview" +msgstr "Stille einfügen" + +#: gtk_ardour/editor.cc:3647 +#, fuzzy +msgid "set selected control point" +msgstr "Synchronisationspunkt entfernen" + +#: gtk_ardour/editor.cc:3719 +#, fuzzy +msgid "set selected regionview" +msgstr "Auswahl zu Schleife machen" + +#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835 +#, fuzzy +msgid "set selected regions" +msgstr "Auswahl zu Schleife machen" + +#: gtk_ardour/editor.cc:3891 +msgid "Undo" +msgstr "Rückgängig" + +#: gtk_ardour/editor.cc:3893 +msgid "Undo (%1)" +msgstr "Rückgängig (%1)" + +#: gtk_ardour/editor.cc:3903 +msgid "Redo" +msgstr "Wiederherstellen" + +#: gtk_ardour/editor.cc:3905 +msgid "Redo (%1)" +msgstr "Wiederherstellen (%1)" + +#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946 +msgid "... as new track" +msgstr "" + +#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947 +#, fuzzy +msgid "... as new region" +msgstr "Ardour: Region" + +#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452 +#, fuzzy +msgid "Import audio (copy)" +msgstr "Audio Importieren" + +#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457 +msgid "Embed audio (link)" +msgstr "" + +#: gtk_ardour/editor.cc:3953 +#, fuzzy +msgid "Remove last capture" +msgstr "Synchronisationspunkt entfernen" + +#: gtk_ardour/editor.cc:3974 +msgid "Duplicate how many times?" +msgstr "Wie häufig duplizieren?" + +#: gtk_ardour/editor.cc:4550 +msgid "" +"Playlist %1 is currently unused.\n" +"If left alone, no audio files used by it will be cleaned.\n" +"If deleted, audio files used by it alone by will cleaned." +msgstr "" + +#: gtk_ardour/editor.cc:4555 +#, fuzzy +msgid "Delete playlist" +msgstr "Name für Schnappschuß" + +#: gtk_ardour/editor.cc:4556 +#, fuzzy +msgid "Keep playlist" +msgstr "Name für Schnappschuß" + +#: gtk_ardour/editor.cc:4557 +#, fuzzy +msgid "Cancel cleanup" +msgstr "leeren" + +#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258 +#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290 +msgid "" +"programming error: control point canvas item has no control point object " +"pointer!" +msgstr "" + +#: gtk_ardour/editor_canvas_events.cc:717 +msgid "programming error: line canvas item has no line object pointer!" +msgstr "" + +#: gtk_ardour/editor_canvas_events.cc:744 +#: gtk_ardour/editor_canvas_events.cc:784 +#: gtk_ardour/editor_canvas_events.cc:823 +msgid "programming error: no \"rect\" pointer associated with selection item" +msgstr "" + +#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298 +#: gtk_ardour/mixer_ui.cc:670 +msgid "Show All" +msgstr "Alles zeigen" + +#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299 +#: gtk_ardour/mixer_ui.cc:671 +msgid "Hide All" +msgstr "Alle verstecken" + +#: gtk_ardour/editor_edit_groups.cc:98 +msgid "Name for new edit group" +msgstr "" + +#: gtk_ardour/editor_export_audio.cc:60 +msgid "" +"There is no range to export.\n" +"\n" +"Select a range using the range mouse mode" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707 +msgid "programming error: no ImageFrameView selected" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930 +msgid "programming error: no MarkerView selected" +msgstr "" + +#: gtk_ardour/editor_keys.cc:187 +#, fuzzy +msgid "keyboard selection" +msgstr "Auswahl zu Abschnitt machen" + +#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376 +#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526 +#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584 +#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650 +#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700 +#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960 +#: gtk_ardour/editor_mouse.cc:4075 +msgid "programming error: marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681 +msgid "remove marker" +msgstr "" + +#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494 +#, fuzzy +msgid "Locate to" +msgstr "Stellen" + +#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495 +#, fuzzy +msgid "Play from" +msgstr "Wiedergabe ab Anfang" + +#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496 +#, fuzzy +msgid "Set from playhead" +msgstr "Wiedergabe ab Playhead" + +#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497 +#, fuzzy +msgid "Set from range" +msgstr "Ausgewählten Bereich wiedergeben" + +#: gtk_ardour/editor_markers.cc:479 +#, fuzzy +msgid "Set Loop Range" +msgstr "Ausgewählten Bereich wiedergeben" + +#: gtk_ardour/editor_markers.cc:480 +msgid "Set Punch Range" +msgstr "" + +#: gtk_ardour/editor_markers.cc:736 +#, fuzzy +msgid "ardour: rename mark" +msgstr "Ardour: Region umbenennen" + +#: gtk_ardour/editor_markers.cc:738 +#, fuzzy +msgid "ardour: rename range" +msgstr "Ardour: Region umbenennen" + +#: gtk_ardour/editor_markers.cc:792 +#, fuzzy +msgid "set loop range" +msgstr "Ausgewählten Bereich wiedergeben" + +#: gtk_ardour/editor_markers.cc:818 +#, fuzzy +msgid "set punch range" +msgstr "Ausgewählten Bereich wiedergeben" + +#: gtk_ardour/editor_mouse.cc:99 +msgid "Editor::event_frame() used on unhandled event type %1" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1555 +msgid "programming error: start_grab called without drag item" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1760 +msgid "change fade in length" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1778 +msgid "programming error: fade out canvas item has no regionview data pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1852 +#, fuzzy +msgid "change fade out length" +msgstr "Ardour: Editor" + +#: gtk_ardour/editor_mouse.cc:1871 +msgid "programming error: cursor canvas item has no cursor data pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470 +msgid "" +"programming error: meter marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2163 +msgid "move meter mark" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335 +#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439 +msgid "" +"programming error: tempo marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340 +#: gtk_ardour/editor_tempodisplay.cc:425 +msgid "programming error: marker for tempo is not a tempo marker!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2245 +msgid "move tempo mark" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2388 +msgid "programming error: line canvas item has no line pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2497 +#, fuzzy +msgid "move region(s)" +msgstr "Name für Region:" + +#: gtk_ardour/editor_mouse.cc:2509 +msgid "Drag region copy" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2579 +#, fuzzy +msgid "copy region(s)" +msgstr "Ardour: Region" + +#: gtk_ardour/editor_mouse.cc:2612 +#, fuzzy +msgid "Drag region brush" +msgstr "Ardour: Region" + +#: gtk_ardour/editor_mouse.cc:3425 +#, fuzzy +msgid "selection grab" +msgstr "Auswahl" + +#: gtk_ardour/editor_mouse.cc:3571 +#, fuzzy +msgid "range selection" +msgstr "Auswahl wiedergeben" + +#: gtk_ardour/editor_mouse.cc:3587 +#, fuzzy +msgid "trim selection start" +msgstr "Auswahl zu Abschnitt machen" + +#: gtk_ardour/editor_mouse.cc:3603 +#, fuzzy +msgid "trim selection end" +msgstr "Auswahl zu Abschnitt machen" + +#: gtk_ardour/editor_mouse.cc:3620 +#, fuzzy +msgid "move selection" +msgstr "Auswahl zu Schleife machen" + +#: gtk_ardour/editor_mouse.cc:3995 +msgid "Start point trim" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:4023 +msgid "End point trim" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:4062 +#, fuzzy +msgid "trimmed region" +msgstr "Ardour: Region" + +#: gtk_ardour/editor_mouse.cc:4203 +#, fuzzy +msgid "new range marker" +msgstr "Ardour: Region umbenennen" + +#: gtk_ardour/editor_mouse.cc:4422 +#, fuzzy +msgid "select regions" +msgstr "Auswahl zu Schleife machen" + +#: gtk_ardour/editor_mouse.cc:4451 +msgid "Name for region:" +msgstr "Name für Region:" + +#: gtk_ardour/editor_mouse.cc:4517 +#, fuzzy +msgid "timestretch" +msgstr "Ardour: Mixer" + +#: gtk_ardour/editor_ops.cc:117 +#, fuzzy +msgid "split" +msgstr "Teilen" + +#: gtk_ardour/editor_ops.cc:153 +#, fuzzy +msgid "remove region" +msgstr "Name für Region:" + +#: gtk_ardour/editor_ops.cc:172 +msgid "" +" This is destructive, will possibly delete audio files\n" +"It cannot be undone\n" +"Do you really want to destroy %1 ?" +msgstr "" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "these regions" +msgstr "Name für Region:" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "this region" +msgstr "Name für Region:" + +#: gtk_ardour/editor_ops.cc:179 +#, fuzzy +msgid "Yes, destroy them." +msgstr "Ja, entfernen." + +#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434 +#, fuzzy +msgid "Yes, destroy it." +msgstr "Ja, entfernen." + +#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435 +#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300 +msgid "No, do nothing." +msgstr "Nein, nichts machen." + +#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307 +#, fuzzy +msgid "extend selection" +msgstr "Auswahl zu Abschnitt machen" + +#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357 +#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427 +msgid "nudge forward" +msgstr "" + +#: gtk_ardour/editor_ops.cc:491 +msgid "build_region_boundary_cache called with snap_type = %1" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1305 +#, fuzzy +msgid "set selection from range" +msgstr "Ausgewählten Bereich wiedergeben" + +#: gtk_ardour/editor_ops.cc:1421 +msgid "clear markers" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1433 +#, fuzzy +msgid "clear ranges" +msgstr "Verbindungen löschen" + +#: gtk_ardour/editor_ops.cc:1452 +#, fuzzy +msgid "clear locations" +msgstr "Verbindungen löschen" + +#: gtk_ardour/editor_ops.cc:1503 +#, fuzzy +msgid "insert dragged region" +msgstr "Ardour: Region" + +#: gtk_ardour/editor_ops.cc:1538 +#, fuzzy +msgid "insert region" +msgstr "Name für Region:" + +#: gtk_ardour/editor_ops.cc:1744 +msgid "ardour: rename region" +msgstr "Ardour: Region umbenennen" + +#: gtk_ardour/editor_ops.cc:1891 +msgid "You can't import an audiofile until you have a session loaded." +msgstr "" +"Sie können keine Audio-Daten importieren, solange keine Sitzung geladen ist." + +#: gtk_ardour/editor_ops.cc:1901 +#, fuzzy +msgid "Import selected as tracks" +msgstr "Auswahl importieren" + +#: gtk_ardour/editor_ops.cc:1904 +#, fuzzy +msgid "Import selected to region list" +msgstr "Auswahl zu Schleife machen" + +#: gtk_ardour/editor_ops.cc:1933 +msgid "ardour: audio import in progress" +msgstr "Ardour: Audio Import in Arbeit" + +#: gtk_ardour/editor_ops.cc:1937 +msgid "Cancel Import" +msgstr "Importieren Abbrechen" + +#: gtk_ardour/editor_ops.cc:1944 +#, fuzzy +msgid "ardour: importing %1" +msgstr "Ardour: Exportieren" + +#: gtk_ardour/editor_ops.cc:1990 +msgid "%1 it anyway" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1996 +#, fuzzy +msgid "Don't %1 it" +msgstr "Ohne %1" + +#: gtk_ardour/editor_ops.cc:1997 +msgid "%1 all without questions" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1998 +#, fuzzy +msgid "Cancel entire import" +msgstr "Importieren Abbrechen" + +#: gtk_ardour/editor_ops.cc:2004 +msgid "" +"%1\n" +"This audiofile's sample rate doesn't match the session sample rate!" +msgstr "" + +#: gtk_ardour/editor_ops.cc:2032 +#, fuzzy +msgid "You can't embed an audiofile until you have a session loaded." +msgstr "" +"Sie können keine Audio-Daten importieren, solange keine Sitzung geladen ist." + +#: gtk_ardour/editor_ops.cc:2039 +#, fuzzy +msgid "Add to External Region list" +msgstr "Ardour: Region" + +#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210 +#: gtk_ardour/editor_ops.cc:2286 +msgid "Editor: cannot open file \"%1\" (%2)" +msgstr "" + +#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312 +msgid "could not open %1" +msgstr "Konnte \"%s\" nicht öffnen." + +#: gtk_ardour/editor_ops.cc:2171 +#, fuzzy +msgid "Insert selected as new tracks" +msgstr "Stille einfügen" + +#: gtk_ardour/editor_ops.cc:2186 +#, fuzzy +msgid "Insert selected" +msgstr "Stille einfügen" + +#: gtk_ardour/editor_ops.cc:2327 +#, fuzzy +msgid "insert sndfile" +msgstr "Stille einfügen" + +#: gtk_ardour/editor_ops.cc:2464 +#, fuzzy +msgid "separate" +msgstr "Ausgewählten Bereich wiedergeben" + +#: gtk_ardour/editor_ops.cc:2528 +#, fuzzy +msgid "trim to selection" +msgstr "Auswahl zu Abschnitt machen" + +#: gtk_ardour/editor_ops.cc:2568 +msgid "region fill" +msgstr "" + +#: gtk_ardour/editor_ops.cc:2626 +#, fuzzy +msgid "fill selection" +msgstr "Auswahl zu Schleife machen" + +#: gtk_ardour/editor_ops.cc:2650 +msgid "Place the edit cursor at the desired sync point" +msgstr "" +"Positionieren sie den Arbeits-Cursor am gewünschten Synchronisationspunkt" + +#: gtk_ardour/editor_ops.cc:2656 +#, fuzzy +msgid "set sync from edit cursor" +msgstr "Wiedergabe ab Cursor" + +#: gtk_ardour/editor_ops.cc:2668 +#, fuzzy +msgid "remove sync" +msgstr "Synchronisationspunkt entfernen" + +#: gtk_ardour/editor_ops.cc:2682 +#, fuzzy +msgid "naturalize" +msgstr "Ardour: Region" + +#: gtk_ardour/editor_ops.cc:2746 +msgid "align selection (relative)" +msgstr "" + +#: gtk_ardour/editor_ops.cc:2774 +#, fuzzy +msgid "align selection" +msgstr "Auswahl zu Schleife machen" + +#: gtk_ardour/editor_ops.cc:2786 +#, fuzzy +msgid "align region" +msgstr "Ardour: Region" + +#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858 +msgid "trim to edit" +msgstr "" + +#: gtk_ardour/editor_ops.cc:2909 +#, fuzzy +msgid "ardour: freeze" +msgstr "Ardour: " + +#: gtk_ardour/editor_ops.cc:2914 +#, fuzzy +msgid "Cancel Freeze" +msgstr "Abbrechen" + +#: gtk_ardour/editor_ops.cc:2951 +#, fuzzy +msgid "bounce range" +msgstr "Bereich" + +#: gtk_ardour/editor_ops.cc:3004 +#, fuzzy +msgid "cut" +msgstr "Ausschneiden" + +#: gtk_ardour/editor_ops.cc:3007 +#, fuzzy +msgid "copy" +msgstr "Kopieren" + +#: gtk_ardour/editor_ops.cc:3020 +#, fuzzy +msgid " objects" +msgstr "Objekt" + +#: gtk_ardour/editor_ops.cc:3046 +#, fuzzy +msgid " range" +msgstr "Bereich" + +#: gtk_ardour/editor_ops.cc:3201 +#, fuzzy +msgid "paste" +msgstr "Einfügen" + +#: gtk_ardour/editor_ops.cc:3236 +#, fuzzy +msgid "paste chunk" +msgstr "Abschnitt erzeugen:" + +#: gtk_ardour/editor_ops.cc:3276 +#, fuzzy +msgid "duplicate region" +msgstr "Auswahl zu Schleife machen" + +#: gtk_ardour/editor_ops.cc:3309 +#, fuzzy +msgid "duplicate selection" +msgstr "Auswahl zu Schleife machen" + +#: gtk_ardour/editor_ops.cc:3349 +#, fuzzy +msgid "clear playlist" +msgstr "Name für Schnappschuß" + +#: gtk_ardour/editor_ops.cc:3378 +#, fuzzy +msgid "nudge track" +msgstr "Stille einfügen" + +#: gtk_ardour/editor_ops.cc:3431 +#, fuzzy +msgid "" +"Do you really want to destroy the last capture?\n" +"(This is destructive and cannot be undone)" +msgstr "" +"Wollen Sie wirklich die Spur \"%1\" löschen?\n" +"(Kann nicht rückgängig gemacht werden!)" + +#: gtk_ardour/editor_ops.cc:3463 +#, fuzzy +msgid "normalize" +msgstr "Ardour: Region" + +#: gtk_ardour/editor_ops.cc:3510 +#, fuzzy +msgid "reverse regions" +msgstr "Name für Region:" + +#: gtk_ardour/editor_region_list.cc:223 +#, fuzzy +msgid "hidden" +msgstr "Verbergen" + +#: gtk_ardour/editor_region_list.cc:408 +msgid "Show all" +msgstr "Alle zeigen" + +#: gtk_ardour/editor_region_list.cc:417 +msgid "Ascending" +msgstr "aufsteigend" + +#: gtk_ardour/editor_region_list.cc:419 +msgid "Descending" +msgstr "absteigend" + +#: gtk_ardour/editor_region_list.cc:423 +msgid "By Region Name" +msgstr "nach Name der Region" + +#: gtk_ardour/editor_region_list.cc:425 +msgid "By Region Length" +msgstr "nach Länge der Region" + +#: gtk_ardour/editor_region_list.cc:427 +#, fuzzy +msgid "By Region Position" +msgstr "nach Zeitstempel der Region" + +#: gtk_ardour/editor_region_list.cc:429 +msgid "By Region Timestamp" +msgstr "nach Zeitstempel der Region" + +#: gtk_ardour/editor_region_list.cc:431 +msgid "By Region Start in File" +msgstr "nach Anfang der Region in der Datei" + +#: gtk_ardour/editor_region_list.cc:433 +msgid "By Region End in File" +msgstr "nach Ende der Region in der Datei" + +#: gtk_ardour/editor_region_list.cc:435 +msgid "By Source File Name" +msgstr "nach Namen der Quelldatei" + +#: gtk_ardour/editor_region_list.cc:437 +msgid "By Source File Length" +msgstr "nach Länge der Quelldatei" + +#: gtk_ardour/editor_region_list.cc:439 +msgid "By Source File Creation Date" +msgstr "nach Erstellungsdatum der Quelldatei" + +#: gtk_ardour/editor_region_list.cc:441 +msgid "By Source Filesystem" +msgstr "nach Dateisystem der Quelle" + +#: gtk_ardour/editor_region_list.cc:444 +msgid "Sorting" +msgstr "Sortieren" + +#: gtk_ardour/editor_region_list.cc:808 +#, fuzzy +msgid "Regions/length" +msgstr "nach Länge der Region" + +#: gtk_ardour/editor_region_list.cc:812 +#, fuzzy +msgid "Regions/position" +msgstr "Regionen" + +#: gtk_ardour/editor_region_list.cc:816 +#, fuzzy +msgid "Regions/creation" +msgstr "Regionen" + +#: gtk_ardour/editor_region_list.cc:820 +#, fuzzy +msgid "Regions/start" +msgstr "Regionen" + +#: gtk_ardour/editor_region_list.cc:824 +#, fuzzy +msgid "Regions/end" +msgstr "Regionen" + +#: gtk_ardour/editor_region_list.cc:828 +#, fuzzy +msgid "Regions/file name" +msgstr "nach Name der Region" + +#: gtk_ardour/editor_region_list.cc:832 +msgid "Regions/file size" +msgstr "" + +#: gtk_ardour/editor_region_list.cc:836 +msgid "Regions/file date" +msgstr "" + +#: gtk_ardour/editor_region_list.cc:840 +msgid "Regions/file system" +msgstr "" + +#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73 +#: gtk_ardour/editor_route_list.cc:231 +msgid "editor" +msgstr "" + +#: gtk_ardour/editor_route_list.cc:300 +msgid "Show All AbstractTracks" +msgstr "" + +#: gtk_ardour/editor_route_list.cc:301 +msgid "Hide All AbstractTracks" +msgstr "" + +#: gtk_ardour/editor_route_list.cc:302 +msgid "Show All AudioBus" +msgstr "" + +#: gtk_ardour/editor_route_list.cc:303 +msgid "Hide All AudioBus" +msgstr "" + +#: gtk_ardour/editor_rulers.cc:311 +#, fuzzy +msgid "New location marker" +msgstr "Stellen" + +#: gtk_ardour/editor_rulers.cc:312 +#, fuzzy +msgid "Clear all locations" +msgstr "Verbindungen löschen" + +#: gtk_ardour/editor_rulers.cc:317 +#, fuzzy +msgid "Clear all ranges" +msgstr "Verbindungen löschen" + +#: gtk_ardour/editor_rulers.cc:326 +msgid "New Tempo" +msgstr "" + +#: gtk_ardour/editor_rulers.cc:327 +#, fuzzy +msgid "Clear tempo" +msgstr "leeren" + +#: gtk_ardour/editor_rulers.cc:332 +msgid "New Meter" +msgstr "" + +#: gtk_ardour/editor_rulers.cc:333 +#, fuzzy +msgid "Clear meter" +msgstr "leeren" + +#: gtk_ardour/editor_rulers.cc:341 +#, fuzzy +msgid "Min:Secs" +msgstr "Min:Sek" + +#: gtk_ardour/editor_selection_list.cc:117 +msgid "name for chunk:" +msgstr "Name für Abschnitt:" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Create chunk" +msgstr "Abschnitt erzeugen:" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Forget it" +msgstr "Abbrechen" + +#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295 +#, fuzzy +msgid "add" +msgstr "Hinzufügen" + +#: gtk_ardour/editor_tempodisplay.cc:276 +#, fuzzy +msgid "add tempo mark" +msgstr "Ardour: Region umbenennen" + +#: gtk_ardour/editor_tempodisplay.cc:318 +#, fuzzy +msgid "add meter mark" +msgstr "Ardour: Region umbenennen" + +#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383 +#, fuzzy +msgid "done" +msgstr "keine" + +#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404 +msgid "replace tempo mark" +msgstr "" + +#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475 +msgid "programming error: marker for meter is not a meter marker!" +msgstr "" + +#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487 +#, fuzzy +msgid "remove tempo mark" +msgstr "Ja, entfernen." + +#: gtk_ardour/editor_timefx.cc:50 +msgid "Quick but Ugly" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:51 +msgid "Skip Anti-aliasing" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:53 +msgid "Stretch/Shrink it" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:57 +#, fuzzy +msgid "ardour: timestretch" +msgstr "Ardour: Mixer" + +#: gtk_ardour/editor_timefx.cc:58 +msgid "TimeStretchDialog" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83 +#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85 +msgid "TimeStretchButton" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:86 +msgid "TimeStretchProgress" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:151 +msgid "timestretch cannot be started - thread creation error" +msgstr "" + +#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410 +#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189 +msgid "22.05kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413 +#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949 +#: gtk_ardour/export_dialog.cc:1191 +msgid "44.1kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416 +#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193 +msgid "48kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419 +#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195 +msgid "88.2kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422 +#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197 +msgid "96kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425 +#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199 +msgid "192kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:73 +msgid "best" +msgstr "bestmöglich" + +#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964 +msgid "fastest" +msgstr "schnellstmöglich" + +#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966 +msgid "linear" +msgstr "" + +#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968 +msgid "better" +msgstr "besser" + +#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970 +msgid "intermediate" +msgstr "mittelmäßig" + +#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979 +msgid "Rectangular" +msgstr "rechteckig" + +#: gtk_ardour/export_dialog.cc:84 +msgid "Shaped Noise" +msgstr "" + +#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981 +msgid "Triangular" +msgstr "dreieckig" + +#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336 +msgid "stereo" +msgstr "" + +#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497 +#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219 +#: gtk_ardour/utils.cc:334 +msgid "mono" +msgstr "" + +#: gtk_ardour/export_dialog.cc:97 +msgid "CUE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:98 +msgid "TOC" +msgstr "" + +#: gtk_ardour/export_dialog.cc:106 +msgid "FORMAT" +msgstr "" + +#: gtk_ardour/export_dialog.cc:107 +msgid "SAMPLE RATE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:108 +msgid "CONVERSION QUALITY" +msgstr "" + +#: gtk_ardour/export_dialog.cc:109 +msgid "DITHER TYPE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:110 +msgid "CD MARKER FILE TYPE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:111 +msgid "CHANNELS" +msgstr "" + +#: gtk_ardour/export_dialog.cc:112 +msgid "FILE TYPE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:113 +msgid "SAMPLE FORMAT" +msgstr "" + +#: gtk_ardour/export_dialog.cc:114 +msgid "SAMPLE ENDIANNESS" +msgstr "" + +#: gtk_ardour/export_dialog.cc:115 +msgid "EXPORT CD MARKER FILE ONLY" +msgstr "" + +#: gtk_ardour/export_dialog.cc:116 +msgid "EXPORT TO FILE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118 +#: gtk_ardour/option_editor.cc:119 +msgid "Browse" +msgstr "" + +#: gtk_ardour/export_dialog.cc:119 +msgid "Specific tracks ..." +msgstr "" + +#: gtk_ardour/export_dialog.cc:131 +msgid "ardour: export" +msgstr "Ardour: Exportieren" + +#: gtk_ardour/export_dialog.cc:132 +#, fuzzy +msgid "ardour_export" +msgstr "Ardour: Exportieren" + +#: gtk_ardour/export_dialog.cc:156 +#, fuzzy +msgid "Output" +msgstr "Ausgänge" + +#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626 +msgid "Track" +msgstr "Spur" + +#: gtk_ardour/export_dialog.cc:287 +msgid "slereg" +msgstr "" + +#: gtk_ardour/export_dialog.cc:658 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD toc file" +msgstr "" +"Editor: Kann \"%1\" nicht öffnen um CD Track Markierungen zu exportieren." + +#: gtk_ardour/export_dialog.cc:780 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD cue file" +msgstr "" +"Editor: Kann \"%1\" nicht öffnen um CD Track Markierungen zu exportieren." + +#: gtk_ardour/export_dialog.cc:799 +msgid "WAV" +msgstr "" + +#: gtk_ardour/export_dialog.cc:1051 +msgid "Stop Export" +msgstr "Export Abbrechen" + +#: gtk_ardour/gain_automation_time_axis.cc:60 +#, fuzzy +msgid "add gain automation event" +msgstr "Stellen" + +#: gtk_ardour/gain_meter.cc:68 +msgid "Cannot create slider pixmaps" +msgstr "" + +#: gtk_ardour/gain_meter.cc:83 +msgid "dbFS" +msgstr "" + +#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134 +#: gtk_ardour/gain_meter.cc:728 +msgid "pre" +msgstr "" + +#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724 +#, fuzzy +msgid "input" +msgstr "%1 Eingang" + +#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732 +#, fuzzy +msgid "post" +msgstr "Anschluß" + +#: gtk_ardour/gain_meter.cc:146 +msgid "tupni" +msgstr "" + +#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470 +#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537 +msgid "-inf" +msgstr "" + +#: gtk_ardour/imageframe_socket_handler.cc:127 +msgid "Image Compositor Socket has been shutdown/closed" +msgstr "" + +#: gtk_ardour/imageframe_time_axis.cc:295 +#, fuzzy +msgid "0.5 seconds" +msgstr "Minuten:Sekunden" + +#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259 +#, fuzzy +msgid "1 seconds" +msgstr "Minuten:Sekunden" + +#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260 +#, fuzzy +msgid "1.5 seconds" +msgstr "Minuten:Sekunden" + +#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261 +#, fuzzy +msgid "2 seconds" +msgstr "Minuten:Sekunden" + +#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262 +#, fuzzy +msgid "2.5 seconds" +msgstr "Minuten:Sekunden" + +#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263 +#, fuzzy +msgid "3 seconds" +msgstr "Minuten:Sekunden" + +#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268 +#, fuzzy +msgid "Duration (sec)" +msgstr "Ardour: Region" + +#: gtk_ardour/imageframe_time_axis.cc:310 +#, fuzzy +msgid "Remove Frame" +msgstr "Feld entfernen" + +#: gtk_ardour/imageframe_time_axis.cc:313 +msgid "Image Frame" +msgstr "" + +#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274 +#, fuzzy +msgid "Rename Track" +msgstr "Umbenennen" + +#: gtk_ardour/io_selector.cc:64 +msgid "%1 input" +msgstr "%1 Eingang" + +#: gtk_ardour/io_selector.cc:66 +msgid "%1 output" +msgstr "%1 Ausgang" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103 +#, fuzzy +msgid "Inputs" +msgstr "Eingänge" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104 +#, fuzzy +msgid "Outputs" +msgstr "Ausgänge" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Input" +msgstr "Port hinzufügen" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Output" +msgstr "%1 Ausgang" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Input" +msgstr "Synchronisationspunkt entfernen" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Output" +msgstr "Ausgänge" + +#: gtk_ardour/io_selector.cc:144 +#, fuzzy +msgid "Disconnect All" +msgstr "Trennen" + +#: gtk_ardour/io_selector.cc:158 +msgid "Available connections" +msgstr "Verfügbare Verbindungen" + +#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636 +#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724 +msgid "port" +msgstr "Anschluß" + +#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587 +msgid "There are no more JACK ports available." +msgstr "" + +#: gtk_ardour/io_selector.cc:790 +msgid "ardour: " +msgstr "Ardour: " + +#: gtk_ardour/keyboard.cc:419 +msgid "KeyboardTarget: keyname \"%1\" is unknown." +msgstr "" + +#: gtk_ardour/keyboard.cc:645 +msgid "" +"Your system is completely broken - NumLock uses \"%1\"as its modifier. This " +"is madness - see the man page for xmodmap to find out how to fix this." +msgstr "" + +#: gtk_ardour/keyboard.cc:653 +msgid "" +"Your system generates \"%1\" when the NumLock key is pressed. This can cause " +"problems when editing so Ardour will use %2 to mean Meta rather than %1" +msgstr "" + +#: gtk_ardour/keyboard.cc:714 +msgid "You have %1 keys bound to \"mod1\"" +msgstr "" + +#: gtk_ardour/keyboard.cc:729 +msgid "You have %1 keys bound to \"mod2\"" +msgstr "" + +#: gtk_ardour/keyboard.cc:744 +msgid "You have %1 keys bound to \"mod3\"" +msgstr "" + +#: gtk_ardour/keyboard.cc:759 +msgid "You have %1 keys bound to \"mod4\"" +msgstr "" + +#: gtk_ardour/keyboard.cc:774 +msgid "You have %1 keys bound to \"mod5\"" +msgstr "" + +#: gtk_ardour/keyboard_target.cc:72 +msgid "KeyboardTarget: empty string passed to add_binding." +msgstr "" + +#: gtk_ardour/keyboard_target.cc:78 +msgid "KeyboardTarget: no translation found for \"%1\"" +msgstr "" + +#: gtk_ardour/keyboard_target.cc:83 +msgid "KeyboardTarget: unknown action \"%1\"" +msgstr "" + +#: gtk_ardour/keyboard_target.cc:248 +msgid "misformed binding node - ignored" +msgstr "" + +#: gtk_ardour/library_ui.cc:62 +#, fuzzy +msgid "Soundfile Library" +msgstr "Ardour: Audio Bibliothek" + +#: gtk_ardour/library_ui.cc:63 +#, fuzzy +msgid "Filesystem" +msgstr "nach Dateisystem der Quelle" + +#: gtk_ardour/library_ui.cc:66 +msgid "Split Channels" +msgstr "" + +#: gtk_ardour/library_ui.cc:69 +#, fuzzy +msgid "ardour: soundfile selector" +msgstr "Ardour: Farbe auswählen" + +#: gtk_ardour/library_ui.cc:430 +msgid "Add to Library..." +msgstr "Zu Bibliothek hinzufügen..." + +#: gtk_ardour/library_ui.cc:431 +msgid "Remove..." +msgstr "Entfernen..." + +#: gtk_ardour/library_ui.cc:432 +msgid "Find..." +msgstr "Suchen..." + +#: gtk_ardour/library_ui.cc:433 +msgid "Add Folder" +msgstr "Verzeichnis hinzufügen" + +#: gtk_ardour/library_ui.cc:434 +msgid "Add audio file or directory" +msgstr "Audio-Datei oder -Verzeichnis hinzufügen" + +#: gtk_ardour/library_ui.cc:713 +#, fuzzy +msgid "Importing" +msgstr "Importieren" + +#: gtk_ardour/library_ui.cc:748 +msgid "%1 not added to database" +msgstr "" + +#: gtk_ardour/library_ui.cc:767 +msgid "Folder name:" +msgstr "Verzeichnisname:" + +#: gtk_ardour/library_ui.cc:838 +#, fuzzy +msgid "Should not be reached" +msgstr "Datei \"%1\" konnte nicht geöffnet werden." + +#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096 +msgid "file \"%1\" could not be opened" +msgstr "Datei \"%1\" konnte nicht geöffnet werden." + +#: gtk_ardour/library_ui.cc:956 +msgid "Field" +msgstr "Feld" + +#: gtk_ardour/library_ui.cc:957 +msgid "Value" +msgstr "Wert" + +#: gtk_ardour/library_ui.cc:973 +#, fuzzy +msgid "Stop" +msgstr "Stop" + +#: gtk_ardour/library_ui.cc:974 +msgid "Add Field..." +msgstr "Feld hinzufügen..." + +#: gtk_ardour/library_ui.cc:975 +msgid "Remove Field" +msgstr "Feld entfernen" + +#: gtk_ardour/library_ui.cc:979 +msgid "Soundfile Info" +msgstr "" + +#: gtk_ardour/library_ui.cc:1106 +msgid "file \"%1\" appears not to be an audio file" +msgstr "" + +#: gtk_ardour/library_ui.cc:1159 +msgid "Could not read file: %1 (%2)." +msgstr "" + +#: gtk_ardour/library_ui.cc:1177 +msgid "Could not access soundfile: " +msgstr "" + +#: gtk_ardour/library_ui.cc:1222 +msgid "Field name:" +msgstr "Feldname:" + +#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367 +msgid "Field value:" +msgstr "Wert des Feldes:" + +#: gtk_ardour/library_ui.cc:1295 +msgid "Find" +msgstr "Suchen" + +#: gtk_ardour/library_ui.cc:1296 +msgid "AND" +msgstr "UND" + +#: gtk_ardour/library_ui.cc:1297 +msgid "OR" +msgstr "ODER" + +#: gtk_ardour/library_ui.cc:1300 +msgid "ardour: locate soundfiles" +msgstr "" + +#: gtk_ardour/library_ui.cc:1426 +msgid "Results" +msgstr "Ergebnisse" + +#: gtk_ardour/library_ui.cc:1427 +msgid "Uris" +msgstr "" + +#: gtk_ardour/library_ui.cc:1439 +msgid "Create multi-channel region" +msgstr "Region mit mehreren Kanälen erstellen" + +#: gtk_ardour/library_ui.cc:1442 +msgid "Ardour: Search Results" +msgstr "Ardour: Suchergebnisse" + +#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50 +#, fuzzy +msgid "Set" +msgstr "Auswahl" + +#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51 +msgid "Go" +msgstr "" + +#: gtk_ardour/location_ui.cc:54 +msgid "CD" +msgstr "CD" + +#: gtk_ardour/location_ui.cc:55 +#, fuzzy +msgid "Hidden" +msgstr "Verbergen" + +#: gtk_ardour/location_ui.cc:57 +msgid "SCMS" +msgstr "" + +#: gtk_ardour/location_ui.cc:58 +msgid "Pre-Emphasis" +msgstr "" + +#: gtk_ardour/location_ui.cc:592 +#, fuzzy +msgid "Add New Location" +msgstr "Stellen" + +#: gtk_ardour/location_ui.cc:593 +msgid "Add New Range" +msgstr "" + +#: gtk_ardour/location_ui.cc:597 +msgid "ardour: locations" +msgstr "" + +#: gtk_ardour/location_ui.cc:598 +#, fuzzy +msgid "ardour_locations" +msgstr "Ardour: Verbindungen" + +#: gtk_ardour/location_ui.cc:629 +#, fuzzy +msgid "Location (CD Index) Markers" +msgstr "Stellen" + +#: gtk_ardour/location_ui.cc:649 +msgid "Range (CD Track) Markers" +msgstr "" + +#: gtk_ardour/location_ui.cc:814 +#, fuzzy +msgid "add range marker" +msgstr "Ardour: Region umbenennen" + +#: gtk_ardour/main.cc:76 +msgid "ardour is killing itself for a clean exit\n" +msgstr "" + +#: gtk_ardour/main.cc:85 +msgid "stopping user interface\n" +msgstr "" + +#: gtk_ardour/main.cc:104 +#, c-format +msgid "%d(%d): received signal %d\n" +msgstr "" + +#: gtk_ardour/main.cc:190 +msgid "cannot become new process group leader (%1)" +msgstr "" + +#: gtk_ardour/main.cc:217 +msgid "cannot setup signal handling for %1" +msgstr "" + +#: gtk_ardour/main.cc:228 +msgid "cannot set default signal mask (%1)" +msgstr "" + +#: gtk_ardour/main.cc:253 +msgid "" +"Without a UI style file, ardour will look strange.\n" +" Please set ARDOUR_UI_RC to point to a valid UI style file" +msgstr "" + +#: gtk_ardour/main.cc:292 +msgid "" +"Ardour could not connect to JACK.\n" +"There are several possible reasons:\n" +"\n" +"1) JACK is not running.\n" +"2) JACK is running as another user, perhaps root.\n" +"3) There is already another client called \"ardour\".\n" +"\n" +"Please consider the possibilities, and perhaps (re)start JACK." +msgstr "" + +#: gtk_ardour/main.cc:305 +#, fuzzy +msgid "ardour: unplugged" +msgstr "Ardour: Plugins" + +#: gtk_ardour/main.cc:363 +msgid "Ardour/GTK " +msgstr "" + +#: gtk_ardour/main.cc:365 +msgid "" +"\n" +" (built using " +msgstr "" + +#: gtk_ardour/main.cc:369 +msgid " with libardour " +msgstr "" + +#: gtk_ardour/main.cc:374 +msgid " and GCC version " +msgstr "" + +#: gtk_ardour/main.cc:384 +msgid "Copyright (C) 1999-2005 Paul Davis" +msgstr "" + +#: gtk_ardour/main.cc:385 +msgid "" +"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel " +"Baker" +msgstr "" + +#: gtk_ardour/main.cc:387 +msgid "Ardour comes with ABSOLUTELY NO WARRANTY" +msgstr "Achtung: Es gibt zu Ardour KEINERLEI Gewährleistung!" + +#: gtk_ardour/main.cc:388 +msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +msgstr "" + +#: gtk_ardour/main.cc:389 +msgid "This is free software, and you are welcome to redistribute it " +msgstr "Dies ist freie Software und Sie dürfen sie gerne weiterverbreiten," + +#: gtk_ardour/main.cc:390 +#, fuzzy +msgid "under certain conditions; see the source for copying conditions." +msgstr "solange Sie sich an die Spielregeln aus der Datei COPYING halten." + +#: gtk_ardour/main.cc:399 +msgid "could not create ARDOUR GUI" +msgstr "" + +#: gtk_ardour/main.cc:419 +msgid "Could not connect to JACK server as \"%1\"" +msgstr "" + +#: gtk_ardour/main.cc:424 +msgid "could not initialize Ardour." +msgstr "" + +#: gtk_ardour/main.cc:435 +msgid "could not load command line session \"%1\"" +msgstr "" + +#: gtk_ardour/main.cc:455 +msgid "" +"\n" +"\n" +"A session named \"%1\" already exists.\n" +"To avoid this message, start ardour as \"ardour %1" +msgstr "" + +#: gtk_ardour/main.cc:466 +msgid "" +"\n" +"\n" +"No session named \"%1\" exists.\n" +"To create it from the command line, start ardour as \"ardour --new %1" +msgstr "" + +#: gtk_ardour/marker.cc:354 +#, fuzzy +msgid "MarkerText" +msgstr "Schicht" + +#: gtk_ardour/marker_time_axis.cc:271 +#, fuzzy +msgid "Remove Marker" +msgstr "Feld entfernen" + +#: gtk_ardour/marker_time_axis.cc:273 +#, fuzzy +msgid "Marker" +msgstr "Schicht" + +#: gtk_ardour/meter_bridge.cc:74 +msgid "ardour: meter bridge" +msgstr "" + +#: gtk_ardour/meter_bridge.cc:75 +msgid "ardour_meter_bridge" +msgstr "" + +#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93 +#, c-format +msgid "# of %u-sample overs" +msgstr "" + +#: gtk_ardour/meter_bridge_strip.cc:219 +msgid "New name for meter:" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507 +#: gtk_ardour/region_editor.cc:45 +msgid "mute" +msgstr "mute" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508 +msgid "solo" +msgstr "solo" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506 +msgid "RECORD" +msgstr "AUFNAHME" + +#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514 +msgid "polarity" +msgstr "Polarität" + +#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509 +msgid "comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810 +msgid "INPUT" +msgstr "EINGANG" + +#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831 +msgid "OUTPUT" +msgstr "AUSGANG" + +#: gtk_ardour/mixer_strip.cc:173 +#, fuzzy +msgid "Pan automation mode" +msgstr "Stellen" + +#: gtk_ardour/mixer_strip.cc:174 +#, fuzzy +msgid "Gain automation mode" +msgstr "Stellen" + +#: gtk_ardour/mixer_strip.cc:176 +#, fuzzy +msgid "Pan automation type" +msgstr "Stellen" + +#: gtk_ardour/mixer_strip.cc:177 +#, fuzzy +msgid "Gain automation type" +msgstr "Stellen" + +#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232 +#: gtk_ardour/mixer_strip.cc:979 +#, fuzzy +msgid "trim" +msgstr "Streifen" + +#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233 +#: gtk_ardour/mixer_strip.cc:983 +msgid "abs" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:240 +#, fuzzy +msgid "gain automation mode" +msgstr "Stellen" + +#: gtk_ardour/mixer_strip.cc:241 +#, fuzzy +msgid "pan automation mode" +msgstr "Stellen" + +#: gtk_ardour/mixer_strip.cc:242 +#, fuzzy +msgid "gain automation state" +msgstr "Stellen" + +#: gtk_ardour/mixer_strip.cc:243 +#, fuzzy +msgid "pan automation state" +msgstr "Stellen" + +#: gtk_ardour/mixer_strip.cc:259 +msgid "varispeed" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174 +msgid "click to add/edit comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:463 +msgid "unknown strip width \"%1\" in XML GUI information" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:522 +msgid "REC" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:525 +#, fuzzy +msgid "cmt" +msgstr "Ausschneiden" + +#: gtk_ardour/mixer_strip.cc:530 +msgid "pol" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620 +#: gtk_ardour/redirect_box.cc:1180 +msgid "Not connected to JACK - no I/O changes are possible" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667 +msgid "could not register new ports required for that connection" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:813 +msgid "IN" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:834 +msgid "OUT" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:950 +msgid "aplay" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:956 +msgid "awrite" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:1134 +#, fuzzy +msgid ": comment editor" +msgstr "Der Editor konnte nicht initialisiert werden." + +#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224 +msgid "no group" +msgstr "keine Gruppe" + +#: gtk_ardour/mixer_strip.cc:1227 +msgid "~G" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:52 +msgid "Strips" +msgstr "Streifen" + +#: gtk_ardour/mixer_ui.cc:56 +msgid "Snapshots" +msgstr "Schnapschüsse" + +#: gtk_ardour/mixer_ui.cc:61 +msgid "***" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17 +#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144 +#: gtk_ardour/tempo_dialog.cc:162 +msgid "Bar" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:121 +msgid "Mix Groups" +msgstr "Mix Gruppen" + +#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373 +msgid "ardour: mixer" +msgstr "Ardour: Mixer" + +#: gtk_ardour/mixer_ui.cc:192 +#, fuzzy +msgid "ardour_mixer" +msgstr "Ardour: Mixer" + +#: gtk_ardour/mixer_ui.cc:342 +msgid "ardour: mixer: " +msgstr "Ardour: Mixer: " + +#: gtk_ardour/mixer_ui.cc:641 +msgid "signal" +msgstr "Signal" + +#: gtk_ardour/mixer_ui.cc:672 +msgid "Show All AudioTrack MixerStrips" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:673 +msgid "Hide All AudioTrack MixerStrips" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:674 +msgid "Show All AudioBus MixerStrips" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:675 +msgid "Hide All AudioBus MixerStrips" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:687 +msgid "track display list item for renamed strip not found!" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:700 +msgid "Name for new mix group" +msgstr "Name für neue Mix Gruppe" + +#: gtk_ardour/new_session_dialog.cc:39 +#, fuzzy +msgid "Session name:" +msgstr "Name der Sitzung" + +#: gtk_ardour/new_session_dialog.cc:39 +#, fuzzy +msgid "Create" +msgstr "Abschnitt erzeugen:" + +#: gtk_ardour/new_session_dialog.cc:40 +msgid "use control outs" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:41 +msgid "use master outs" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:42 +msgid "automatically connect track inputs to physical ports" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:43 +msgid "automatically connect track outputs to master outs" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:44 +msgid "automatically connect track outputs to physical ports" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:45 +msgid "manually connect track outputs" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:50 +#, fuzzy +msgid "Advanced..." +msgstr "Feld hinzufügen..." + +#: gtk_ardour/new_session_dialog.cc:52 +#, fuzzy +msgid "show again" +msgstr "Stellen" + +#: gtk_ardour/new_session_dialog.cc:55 +msgid "Hardware Inputs: use" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:56 +msgid "Hardware Outputs: use" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:62 +#, fuzzy +msgid "new session setup" +msgstr "Name der Sitzung" + +#: gtk_ardour/new_session_dialog.cc:63 +#, fuzzy +msgid "ardour_new_session" +msgstr "Ardour: Neue Sitzung" + +#: gtk_ardour/new_session_dialog.cc:72 +msgid "This session will playback and record at %1 Hz" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:74 +msgid "" +"This rate is set by JACK and cannot be changed.\n" +"If you want to use a different sample rate\n" +"please exit and restart JACK" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:155 +#, fuzzy +msgid "Session template" +msgstr "Name der Sitzung" + +#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20 +#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146 +#: gtk_ardour/tempo_dialog.cc:164 +#, fuzzy +msgid "Location" +msgstr "Stellen" + +#: gtk_ardour/new_session_dialog.cc:178 +msgid "Configuration" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:269 +msgid "blank" +msgstr "leer" + +#: gtk_ardour/new_session_dialog.cc:328 +msgid "No template - create tracks/busses manually" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:337 +#, fuzzy +msgid "No template" +msgstr "Voreinstellung" + +#: gtk_ardour/option_editor.cc:48 +#, fuzzy +msgid "Internal" +msgstr "mittelmäßig" + +#: gtk_ardour/option_editor.cc:49 +#, fuzzy +msgid "Slave to MTC" +msgstr "MTC senden" + +#: gtk_ardour/option_editor.cc:50 +msgid "Sync with JACK" +msgstr "" + +#: gtk_ardour/option_editor.cc:51 +msgid "never used but stops crashes" +msgstr "" + +#: gtk_ardour/option_editor.cc:56 +#, fuzzy +msgid "Later regions are higher" +msgstr "Region eine Ebene nach unten" + +#: gtk_ardour/option_editor.cc:57 +msgid "Most recently added/moved/trimmed regions are higher" +msgstr "" + +#: gtk_ardour/option_editor.cc:58 +#, fuzzy +msgid "Most recently added regions are higher" +msgstr "Region eine Ebene nach unten" + +#: gtk_ardour/option_editor.cc:63 +#, fuzzy +msgid "Span entire region overlap" +msgstr "Region eine Ebene nach oben" + +#: gtk_ardour/option_editor.cc:64 +msgid "Short fades at the start of the overlap" +msgstr "" + +#: gtk_ardour/option_editor.cc:82 +msgid "Automatically create crossfades" +msgstr "" + +#: gtk_ardour/option_editor.cc:83 +msgid "New full-overlap crossfades are unmuted" +msgstr "" + +#: gtk_ardour/option_editor.cc:84 +#, fuzzy +msgid "Region layering mode" +msgstr "Regionen" + +#: gtk_ardour/option_editor.cc:85 +msgid "Crossfade model" +msgstr "" + +#: gtk_ardour/option_editor.cc:90 +msgid "Latched solo" +msgstr "" + +#: gtk_ardour/option_editor.cc:91 +msgid "Solo via bus" +msgstr "" + +#: gtk_ardour/option_editor.cc:96 +#, fuzzy +msgid "Show waveforms while recording" +msgstr "Wellenform zeigen" + +#: gtk_ardour/option_editor.cc:97 +#, fuzzy +msgid "Narrow mixer strips" +msgstr "schmale Mixerstreifen" + +#: gtk_ardour/option_editor.cc:98 +msgid "Show measure lines" +msgstr "" + +#: gtk_ardour/option_editor.cc:99 +#, fuzzy +msgid "Follow playhead" +msgstr "Wiedergabe ab Playhead" + +#: gtk_ardour/option_editor.cc:103 +msgid "Send MTC" +msgstr "MTC senden" + +#: gtk_ardour/option_editor.cc:104 +msgid "Send MMC" +msgstr "MMC senden" + +#: gtk_ardour/option_editor.cc:105 +msgid "JACK time master" +msgstr "" + +#: gtk_ardour/option_editor.cc:107 +msgid "SMPTE offset is negative" +msgstr "" + +#: gtk_ardour/option_editor.cc:111 +msgid "Send MIDI parameter feedback" +msgstr "" + +#: gtk_ardour/option_editor.cc:112 +msgid "MIDI parameter control" +msgstr "" + +#: gtk_ardour/option_editor.cc:113 +msgid "MMC control" +msgstr "" + +#: gtk_ardour/option_editor.cc:131 +msgid "Auto-connect new track inputs to hardware" +msgstr "" + +#: gtk_ardour/option_editor.cc:132 +msgid "Auto-connect new track outputs to hardware" +msgstr "" + +#: gtk_ardour/option_editor.cc:133 +msgid "Auto-connect new track outputs to master bus" +msgstr "" + +#: gtk_ardour/option_editor.cc:134 +msgid "Manually connect new track outputs" +msgstr "" + +#: gtk_ardour/option_editor.cc:135 +msgid "Use Hardware Monitoring" +msgstr "" + +#: gtk_ardour/option_editor.cc:136 +msgid "Use Software Monitoring" +msgstr "" + +#: gtk_ardour/option_editor.cc:137 +msgid "Stop plugins with transport" +msgstr "" + +#: gtk_ardour/option_editor.cc:138 +msgid "Run plugins while recording" +msgstr "" + +#: gtk_ardour/option_editor.cc:139 +#, fuzzy +msgid "Verify remove last capture" +msgstr "Synchronisationspunkt entfernen" + +#: gtk_ardour/option_editor.cc:140 +msgid "Stop recording on xrun" +msgstr "" + +#: gtk_ardour/option_editor.cc:141 +#, fuzzy +msgid "Stop transport at end of session" +msgstr "Ans Ende der Sitzung springen" + +#: gtk_ardour/option_editor.cc:142 +msgid "Debug keyboard events" +msgstr "" + +#: gtk_ardour/option_editor.cc:143 +msgid "-12dB gain reduction for ffwd/rew" +msgstr "" + +#: gtk_ardour/option_editor.cc:152 +#, fuzzy +msgid "ardour: options editor" +msgstr "Ardour: Einstellungen" + +#: gtk_ardour/option_editor.cc:153 +#, fuzzy +msgid "ardour_option_editor" +msgstr "Ardour: Einstellungen" + +#: gtk_ardour/option_editor.cc:183 +#, fuzzy +msgid "Misc" +msgstr "Min:Sek" + +#: gtk_ardour/option_editor.cc:184 +msgid "Sync" +msgstr "" + +#: gtk_ardour/option_editor.cc:185 +msgid "Paths/Files" +msgstr "Pfade- und Dateinamen" + +#: gtk_ardour/option_editor.cc:186 +msgid "Display" +msgstr "Anzeige" + +#: gtk_ardour/option_editor.cc:187 +msgid "Kbd/Mouse" +msgstr "" + +#: gtk_ardour/option_editor.cc:188 +msgid "Click" +msgstr "" + +#: gtk_ardour/option_editor.cc:190 +msgid "Layers & Fades" +msgstr "" + +#: gtk_ardour/option_editor.cc:195 +msgid "MIDI" +msgstr "" + +#: gtk_ardour/option_editor.cc:268 +msgid "24 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:270 +msgid "25 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:272 +msgid "30 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:278 +msgid "30 FPS drop" +msgstr "" + +#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379 +#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736 +#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800 +msgid "Medium" +msgstr "" + +#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738 +#: gtk_ardour/option_editor.cc:804 +#, fuzzy +msgid "Faster" +msgstr "Einfügen" + +#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714 +#: gtk_ardour/option_editor.cc:776 +#, fuzzy +msgid "Short" +msgstr "Anschluß" + +#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716 +#: gtk_ardour/option_editor.cc:780 +msgid "Long" +msgstr "" + +#: gtk_ardour/option_editor.cc:396 +msgid "Broadcast WAVE/floating point" +msgstr "" + +#: gtk_ardour/option_editor.cc:397 +msgid "WAVE/floating point" +msgstr "" + +#: gtk_ardour/option_editor.cc:417 +msgid "session RAID path" +msgstr "" + +#: gtk_ardour/option_editor.cc:422 +msgid "Native Format" +msgstr "" + +#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460 +#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409 +#, fuzzy +msgid "internal" +msgstr "mittelmäßig" + +#: gtk_ardour/option_editor.cc:537 +msgid "Short crossfade length (msecs)" +msgstr "" + +#: gtk_ardour/option_editor.cc:710 +msgid "Meter Peak Hold" +msgstr "" + +#: gtk_ardour/option_editor.cc:730 +msgid "Meter Falloff" +msgstr "" + +#: gtk_ardour/option_editor.cc:847 +msgid "Positional Sync" +msgstr "" + +#: gtk_ardour/option_editor.cc:902 +msgid "SMPTE Frames/second" +msgstr "" + +#: gtk_ardour/option_editor.cc:903 +msgid "SMPTE Offset" +msgstr "" + +#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013 +#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211 +#, fuzzy +msgid "online" +msgstr "Verbindungen" + +#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014 +#: gtk_ardour/option_editor.cc:1208 +msgid "offline" +msgstr "" + +#: gtk_ardour/option_editor.cc:1319 +msgid "Use as click" +msgstr "" + +#: gtk_ardour/option_editor.cc:1344 +msgid "Use as click emphasis" +msgstr "" + +#: gtk_ardour/option_editor.cc:1478 +msgid "--unknown--" +msgstr "--unbekannt--" + +#: gtk_ardour/option_editor.cc:1595 +msgid "Click audio file" +msgstr "" + +#: gtk_ardour/option_editor.cc:1601 +msgid "Click emphasis audiofile" +msgstr "" + +#: gtk_ardour/option_editor.cc:1638 +msgid "" +"The auditioner is a dedicated mixer strip used\n" +"for listening to specific regions outside the context\n" +"of the overall mix. It can be connected just like any\n" +"other mixer strip." +msgstr "" + +#: gtk_ardour/option_editor.cc:1887 +#, fuzzy +msgid "Edit using" +msgstr "Mix Gruppen" + +#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924 +msgid "+ button" +msgstr "" + +#: gtk_ardour/option_editor.cc:1917 +#, fuzzy +msgid "Delete using" +msgstr "Messungen" + +#: gtk_ardour/option_editor.cc:1947 +msgid "Ignore snap using" +msgstr "" + +#: gtk_ardour/opts.cc:46 +msgid "Usage: " +msgstr "Aufruf:" + +#: gtk_ardour/opts.cc:47 +msgid " -v, --version Show version information\n" +msgstr " -v, --version Versionsinformation ausgeben\n" + +#: gtk_ardour/opts.cc:48 +msgid " -h, --help Print this message\n" +msgstr " -h, --help Diese Hinweise\n" + +#: gtk_ardour/opts.cc:49 +msgid "" +" -b, --bindings Print all possible keyboard binding " +"names\n" +msgstr "" +" -b, --bindings Alle möglichen Tastenzuweisungsnamen " +"ausgeben\n" + +#: gtk_ardour/opts.cc:50 +#, fuzzy +msgid " -n, --show-splash Show splash screen\n" +msgstr " -h, --help Diese Hinweise\n" + +#: gtk_ardour/opts.cc:51 +#, fuzzy +msgid "" +" -c, --name name Use a specific jack client name, default " +"is ardour\n" +msgstr " -U, --ui-rcfile=FILENAME Dateiname für UI Einstellungen\n" + +#: gtk_ardour/opts.cc:52 +#, fuzzy +msgid "" +" -N, --new session-name Create a new session from the command " +"line\n" +msgstr " [session-name] Name der zu ladenden Sitzung\n" + +#: gtk_ardour/opts.cc:53 +msgid "" +" -o, --use-hw-optimizations Try to use h/w specific optimizations\n" +msgstr "" + +#: gtk_ardour/opts.cc:55 +#, fuzzy +msgid " -V, --novst Do not use VST support\n" +msgstr " -h, --help Diese Hinweise\n" + +#: gtk_ardour/opts.cc:57 +msgid " [session-name] Name of session to load\n" +msgstr " [session-name] Name der zu ladenden Sitzung\n" + +#: gtk_ardour/opts.cc:58 +msgid " -C, --curvetest filename Curve algorithm debugger\n" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:58 +msgid "You can't graphically edit panning of more than stream" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:78 +#, fuzzy +msgid "add pan automation event" +msgstr "Stellen" + +#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441 +msgid "Bypass" +msgstr "" + +#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222 +#, fuzzy +msgid "link" +msgstr "leer" + +#: gtk_ardour/panner_ui.cc:103 +msgid "panning link control" +msgstr "" + +#: gtk_ardour/panner_ui.cc:105 +msgid "panning link direction" +msgstr "" + +#: gtk_ardour/panner_ui.cc:232 +msgid "L" +msgstr "" + +#: gtk_ardour/panner_ui.cc:344 +#, c-format +msgid "panner for channel %u" +msgstr "" + +#: gtk_ardour/panner_ui.cc:451 +#, fuzzy +msgid "Reset all" +msgstr "bestmöglich" + +#: gtk_ardour/playlist_selector.cc:46 +msgid "Playlists grouped by track" +msgstr "" + +#: gtk_ardour/playlist_selector.cc:53 +#, fuzzy +msgid "close" +msgstr "Schließen" + +#: gtk_ardour/playlist_selector.cc:59 +#, fuzzy +msgid "ardour: playlists" +msgstr "Ardour: Plugins" + +#: gtk_ardour/playlist_selector.cc:104 +#, fuzzy +msgid "ardour: playlist for " +msgstr "Ardour: Editor: " + +#: gtk_ardour/playlist_selector.cc:122 +#, fuzzy +msgid "Other tracks" +msgstr "Stille einfügen" + +#: gtk_ardour/playlist_selector.cc:138 +msgid "unassigned" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:41 +msgid "Available LADSPA plugins" +msgstr "Verfügbare LADSPA Plugins" + +#: gtk_ardour/plugin_selector.cc:42 +msgid "Type" +msgstr "Typ" + +#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51 +msgid "# Inputs" +msgstr "Eingänge" + +#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52 +msgid "# Outputs" +msgstr "Ausgänge" + +#: gtk_ardour/plugin_selector.cc:50 +#, fuzzy +msgid "Available VST plugins" +msgstr "Verfügbare LADSPA Plugins" + +#: gtk_ardour/plugin_selector.cc:58 +msgid "To be added" +msgstr "hinzuzufügen" + +#: gtk_ardour/plugin_selector.cc:72 +msgid "ardour: plugins" +msgstr "Ardour: Plugins" + +#: gtk_ardour/plugin_selector.cc:82 +msgid "Add a plugin to the effect list" +msgstr "Plugin zur Effektliste hinzufügen" + +#: gtk_ardour/plugin_selector.cc:84 +msgid "Remove a plugin from the effect list" +msgstr "Plugin aus der Effektliste entfernen" + +#: gtk_ardour/plugin_selector.cc:88 +msgid "Update" +msgstr "Auffrischen" + +#: gtk_ardour/plugin_selector.cc:89 +msgid "Update available plugins" +msgstr "Verfügbare Plugins auffrischen" + +#: gtk_ardour/plugin_selector.cc:110 +msgid "LADSPA" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:113 +msgid "VST" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:83 +msgid "" +"unknown type of editor-supplying plugin (note: no VST support in this " +"version of ardour)" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:269 +msgid "Plugin Editor: could not build control element for port %1" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "in" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "ins" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "out" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "outs" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:382 +#, fuzzy +msgid "automation control" +msgstr "Stellen" + +#: gtk_ardour/plugin_ui.cc:869 +#, fuzzy +msgid "save" +msgstr "Speichern" + +#: gtk_ardour/plugin_ui.cc:870 +msgid "bypass" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:892 +msgid "Plugin preset %1 not found" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:903 +msgid "Name for plugin settings:" +msgstr "Name für Plugineinstellungen:" + +#: gtk_ardour/redirect_automation_line.cc:53 +msgid "redirect automation created for non-plugin" +msgstr "" + +#: gtk_ardour/redirect_automation_time_axis.cc:92 +#, fuzzy +msgid "add automation event to " +msgstr "Stellen" + +#: gtk_ardour/redirect_box.cc:213 +msgid "New send" +msgstr "" + +#: gtk_ardour/redirect_box.cc:214 +msgid "Show send controls" +msgstr "" + +#: gtk_ardour/redirect_box.cc:360 +msgid "New Plugin ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:361 +#, fuzzy +msgid "New Insert" +msgstr "Neuer Eingang" + +#: gtk_ardour/redirect_box.cc:362 +msgid "New Send ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:380 +#, fuzzy +msgid "Select all" +msgstr "Auswahl" + +#: gtk_ardour/redirect_box.cc:381 +#, fuzzy +msgid "Deselect all" +msgstr "Auswahl" + +#: gtk_ardour/redirect_box.cc:389 +#, fuzzy +msgid "Inserts" +msgstr "Stille einfügen" + +#: gtk_ardour/redirect_box.cc:390 +#, fuzzy +msgid "Sends" +msgstr "Minuten:Sekunden" + +#: gtk_ardour/redirect_box.cc:393 +#, fuzzy +msgid "Select all ..." +msgstr "Auswahl" + +#: gtk_ardour/redirect_box.cc:406 +#, fuzzy +msgid "Activate All" +msgstr "Aktiv" + +#: gtk_ardour/redirect_box.cc:407 +#, fuzzy +msgid "Deactivate All" +msgstr "Alles deaktivieren" + +#: gtk_ardour/redirect_box.cc:488 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point, there are\n" +"%3 active signal streams.\n" +"\n" +"This makes no sense - you are throwing away\n" +"part of the signal." +msgstr "" + +#: gtk_ardour/redirect_box.cc:500 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point there are\n" +"only %3 active signal streams.\n" +"\n" +"This makes no sense - unless the plugin supports\n" +"side-chain inputs. A future version of Ardour will\n" +"support this type of configuration." +msgstr "" + +#: gtk_ardour/redirect_box.cc:513 +msgid "" +"You attempted to add a plugin (%1).\n" +"\n" +"The I/O configuration doesn't make sense:\n" +"\n" +"The plugin has %2 inputs and %3 outputs.\n" +"The track/bus has %4 inputs and %5 outputs.\n" +"The insertion point, has %6 active signals.\n" +"\n" +"Ardour does not understand what to do in such situations.\n" +msgstr "" + +#: gtk_ardour/redirect_box.cc:616 +msgid "Pre-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:619 +msgid "Post-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:781 +msgid "" +"You cannot reorder this set of redirects\n" +"in that way because the inputs and\n" +"outputs do not work correctly." +msgstr "" + +#: gtk_ardour/redirect_box.cc:903 +#, fuzzy +msgid "ardour: rename redirect" +msgstr "Ardour: Region umbenennen" + +#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043 +msgid "" +"Copying the set of redirects on the clipboard failed,\n" +"probably because the I/O configuration of the plugins\n" +"could not match the configuration of this track." +msgstr "" + +#: gtk_ardour/redirect_box.cc:1064 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this track?\n" +"(this cannot be undone)" +msgstr "" +"Wollen Sie wirklich die Spur \"%1\" löschen?\n" +"(Kann nicht rückgängig gemacht werden!)" + +#: gtk_ardour/redirect_box.cc:1067 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this bus?\n" +"(this cannot be undone)" +msgstr "" +"Wollen Sie wirklich die Spur \"%1\" löschen?\n" +"(Kann nicht rückgängig gemacht werden!)" + +#: gtk_ardour/redirect_box.cc:1071 +#, fuzzy +msgid "Yes, remove them all" +msgstr "Ja, entfernen." + +#: gtk_ardour/redirect_box.cc:1114 +#, fuzzy +msgid "ardour: %1" +msgstr "Ardour: " + +#: gtk_ardour/redirect_box.cc:1156 +#, fuzzy +msgid "ardour: %1: %2 (by %3)" +msgstr "Ardour: " + +#: gtk_ardour/region_editor.cc:43 +msgid "NAME:" +msgstr "" + +#: gtk_ardour/region_editor.cc:44 +msgid "lock" +msgstr "" + +#: gtk_ardour/region_editor.cc:46 +msgid "opaque" +msgstr "" + +#: gtk_ardour/region_editor.cc:49 +msgid "Layer" +msgstr "Schicht" + +#: gtk_ardour/region_editor.cc:57 +msgid "ENVELOPE" +msgstr "" + +#: gtk_ardour/region_editor.cc:108 +#, fuzzy +msgid "mute this region" +msgstr "Name für Region:" + +#: gtk_ardour/region_editor.cc:109 +msgid "regions underneath this one cannot be heard" +msgstr "" + +#: gtk_ardour/region_editor.cc:110 +msgid "prevent any changes to this region" +msgstr "" + +#: gtk_ardour/region_editor.cc:111 +msgid "use the gain envelope during playback" +msgstr "" + +#: gtk_ardour/region_editor.cc:112 +msgid "show the gain envelope" +msgstr "" + +#: gtk_ardour/region_editor.cc:113 +msgid "use fade in curve during playback" +msgstr "" + +#: gtk_ardour/region_editor.cc:114 +msgid "use fade out curve during playback" +msgstr "" + +#: gtk_ardour/region_editor.cc:115 +msgid "audition this region" +msgstr "" + +#: gtk_ardour/region_editor.cc:148 +msgid "START:" +msgstr "" + +#: gtk_ardour/region_editor.cc:150 +msgid "END:" +msgstr "" + +#: gtk_ardour/region_editor.cc:152 +msgid "LENGTH:" +msgstr "" + +#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198 +#: gtk_ardour/region_editor.cc:234 +msgid "active" +msgstr "" + +#: gtk_ardour/region_editor.cc:179 +msgid "visible" +msgstr "" + +#: gtk_ardour/region_editor.cc:197 +msgid "FADE IN" +msgstr "" + +#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235 +msgid "msecs" +msgstr "" + +#: gtk_ardour/region_editor.cc:233 +msgid "FADE OUT" +msgstr "" + +#: gtk_ardour/region_editor.cc:276 +msgid "ardour: region " +msgstr "Ardour: Region" + +#: gtk_ardour/region_editor.cc:410 +msgid "fade in edit" +msgstr "" + +#: gtk_ardour/region_editor.cc:422 +#, fuzzy +msgid "fade out edit" +msgstr "Ardour: Editor" + +#: gtk_ardour/regionview.cc:1169 +#, fuzzy +msgid "add gain control point" +msgstr "Synchronisationspunkt entfernen" + +#: gtk_ardour/route_params_ui.cc:58 +msgid "Tracks/Buses" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:59 +msgid "Pre Redirects" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:60 +msgid "Post Redirects" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:105 +msgid "Pre-fader Redirects" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:106 +msgid "Post-fader Redirects" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:138 +#, fuzzy +msgid "ardour: track/bus inspector" +msgstr "Ardour: Editor" + +#: gtk_ardour/route_params_ui.cc:139 +#, fuzzy +msgid "ardour_route_parameters" +msgstr "Ardour: Route" + +#: gtk_ardour/route_params_ui.cc:189 +msgid "route display list item for renamed route not found!" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:448 +msgid "NO TRACK" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:669 +#, fuzzy +msgid "ardour: track/bus inspector: " +msgstr "Ardour: Editor" + +#: gtk_ardour/route_params_ui.cc:673 +msgid "No Route Selected" +msgstr "Keine Route ausgewählt" + +#: gtk_ardour/route_params_ui.cc:674 +#, fuzzy +msgid "ardour: track/bus/inspector: no route selected" +msgstr "Ardour: Route: keine Route ausgewählt" + +#: gtk_ardour/route_ui.cc:134 +#, fuzzy +msgid "mute change" +msgstr "Bereich" + +#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220 +#, fuzzy +msgid "solo change" +msgstr "Bereich" + +#: gtk_ardour/route_ui.cc:284 +msgid "rec-enable change" +msgstr "" + +#: gtk_ardour/route_ui.cc:423 +#, fuzzy +msgid "Solo-safe" +msgstr "solo" + +#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474 +msgid "MIDI Bind" +msgstr "" + +#: gtk_ardour/route_ui.cc:445 +msgid "Pre Fader" +msgstr "" + +#: gtk_ardour/route_ui.cc:452 +msgid "Post Fader" +msgstr "" + +#: gtk_ardour/route_ui.cc:459 +msgid "Control Outs" +msgstr "" + +#: gtk_ardour/route_ui.cc:466 +msgid "Main Outs" +msgstr "" + +#: gtk_ardour/route_ui.cc:503 +msgid "mix group solo change" +msgstr "" + +#: gtk_ardour/route_ui.cc:537 +msgid "mix group mute change" +msgstr "" + +#: gtk_ardour/route_ui.cc:553 +msgid "mix group rec-enable change" +msgstr "" + +#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258 +msgid "ardour: color selection" +msgstr "Ardour: Farbe auswählen" + +#: gtk_ardour/route_ui.cc:652 +#, fuzzy +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"You may also lose the playlist used by this track.\n" +"(cannot be undone)" +msgstr "" +"Wollen Sie wirklich die Spur \"%1\" löschen?\n" +"(Kann nicht rückgängig gemacht werden!)" + +#: gtk_ardour/route_ui.cc:654 +msgid "" +"Do you really want to remove bus \"%1\" ?\n" +"(cannot be undone)" +msgstr "" + +#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299 +msgid "Yes, remove it." +msgstr "Ja, entfernen." + +#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358 +msgid "new name: " +msgstr "Neuer Name: " + +#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31 +msgid "Beats per minute" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35 +#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163 +msgid "Beat" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158 +msgid "Meter denominator" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159 +msgid "Beats per bar" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189 +msgid "whole (1)" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191 +msgid "second (2)" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193 +msgid "third (3)" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195 +#: gtk_ardour/tempo_dialog.cc:203 +msgid "quarter (4)" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197 +msgid "eighth (8)" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199 +msgid "sixteenth (16)" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201 +msgid "thirty-second (32)" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:301 +msgid "garbaged note type entry (%1)" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:311 +msgid "incomprehensible note type entry (%1)" +msgstr "" + +#: gtk_ardour/time_axis_view.cc:95 +msgid "gTortnam" +msgstr "" + +#: gtk_ardour/time_axis_view.cc:446 +msgid "Largest" +msgstr "" + +#: gtk_ardour/time_axis_view.cc:447 +#, fuzzy +msgid "Large" +msgstr "Schicht" + +#: gtk_ardour/time_axis_view.cc:448 +#, fuzzy +msgid "Larger" +msgstr "Schicht" + +#: gtk_ardour/time_axis_view.cc:450 +msgid "Smaller" +msgstr "" + +#: gtk_ardour/time_axis_view.cc:451 +#, fuzzy +msgid "Small" +msgstr "Alle zeigen" + +#: gtk_ardour/time_axis_view.cc:785 +msgid "unknown track height name \"%1\" in XML GUI information" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:69 +msgid "TimeAxisViewItemName" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:258 +msgid "new duration %1 frames is out of bounds for %2" +msgstr "" + +#: gtk_ardour/time_selection.cc:40 +msgid "programming error: request for non-existent audio range (%1)!" +msgstr "" + +#: gtk_ardour/utils.cc:57 +msgid "" +"\"\n" +"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+=" +msgstr "" + +#: gtk_ardour/utils.cc:66 +msgid "aeiou" +msgstr "" + +#: gtk_ardour/utils.cc:75 +msgid "AEIOU" +msgstr "" + +#: gtk_ardour/utils.cc:84 +msgid "bcdfghjklmnpqrtvwxyz" +msgstr "" + +#: gtk_ardour/utils.cc:93 +msgid "BCDFGHJKLMNPQRTVWXYZ" +msgstr "" + +#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265 +msgid "bad XPM header %1" +msgstr "" + +#: gtk_ardour/utils.cc:516 +msgid "missing RGBA style for \"%1\"" +msgstr "" + +#: gtk_ardour/visual_time_axis.cc:297 +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Wollen Sie wirklich die Spur \"%1\" löschen?\n" +"(Kann nicht rückgängig gemacht werden!)" + +#: gtk_ardour/visual_time_axis.cc:385 +msgid "A track already exists with that name" +msgstr "" + +#, fuzzy +#~ msgid "Seamless Looping" +#~ msgstr "Ausgewählten Bereich wiedergeben" + +#~ msgid "Export to CD" +#~ msgstr "Export nach CD" + +#~ msgid "No toggle button pixmaps found to match toggle-button-[0-9]*.xpm$" +#~ msgstr "" +#~ "Keine Grafiken für Umschalter-Knöpfe gefunden!\n" +#~ "(Gesuchter Dateiname: \"toggle-button[0-9]*.xpm$\")" + +#~ msgid "" +#~ "No small push button pixmaps found to match small-round-button-[0-9]*.xpm$" +#~ msgstr "" +#~ "Keine Grafiken für kleine Schaltknöpfe gefunden!\n" +#~ "(Gesuchter Dateiname: \"small-round-button[0-9]*.xpm$\")" + +#~ msgid "ardour: tempo editor" +#~ msgstr "Ardour: Tempo bearbeiten" + +#, fuzzy +#~ msgid "ardour_add_track_bus" +#~ msgstr "Ardour: Editor" + +#~ msgid "ok" +#~ msgstr "OK" + +#, fuzzy +#~ msgid "apply" +#~ msgstr "Anwenden" + +#, fuzzy +#~ msgid "Edit left" +#~ msgstr "Bearbeitungs Modus" + +#, fuzzy +#~ msgid "Edit right" +#~ msgstr "Mix Gruppen" + +#, fuzzy +#~ msgid "Edit fade" +#~ msgstr "Bearbeitungs Modus" + +#, fuzzy +#~ msgid "Export region" +#~ msgstr "Name für Region:" + +#, fuzzy +#~ msgid "Bounce region" +#~ msgstr "Bereich" + +#~ msgid "Play selected region" +#~ msgstr "Wiedergabe der ausgewählten Region" + +#~ msgid "clear connections" +#~ msgstr "Verbindungen löschen" diff --git a/gtk2_ardour/po/el_GR.po b/gtk2_ardour/po/el_GR.po new file mode 100644 index 0000000000..f694761af3 --- /dev/null +++ b/gtk2_ardour/po/el_GR.po @@ -0,0 +1,5195 @@ +# Σχολιαστικός Τίτλος. +# Πνευματικά Δικαιώματα (C) YEAR Paul Davis +# Το παÏόν αÏχείο διανέμεται υπό της ιδίας αδείας με του PACKAGE πακέτου. +# ΠΡΩΤΟΣ ΔΗΜΙΟΥΡΓΟΣ , 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.99beta23\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2005-09-19 18:09-0400\n" +"PO-Revision-Date: 2005-01-11\n" +"Last-Translator: Muadibas \n" +"Language-Team: Hellenic(Greek) \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: gtk_ardour/about.cc:134 +msgid "Marcus Andersson" +msgstr "" + +#: gtk_ardour/about.cc:135 +msgid "Jeremy Hall" +msgstr "" + +#: gtk_ardour/about.cc:136 +msgid "Steve Harris" +msgstr "" + +#: gtk_ardour/about.cc:137 +msgid "Tim Mayberry" +msgstr "" + +#: gtk_ardour/about.cc:138 +msgid "Mark Stewart" +msgstr "" + +#: gtk_ardour/about.cc:139 +msgid "Sam Chessman" +msgstr "" + +#: gtk_ardour/about.cc:140 +msgid "Jack O'Quin" +msgstr "" + +#: gtk_ardour/about.cc:141 +msgid "Matt Krai" +msgstr "" + +#: gtk_ardour/about.cc:142 +msgid "Ben Bell" +msgstr "" + +#: gtk_ardour/about.cc:143 +msgid "Gerard van Dongen" +msgstr "" + +#: gtk_ardour/about.cc:144 +msgid "Thomas Charbonnel" +msgstr "" + +#: gtk_ardour/about.cc:145 +msgid "Nick Mainsbridge" +msgstr "" + +#: gtk_ardour/about.cc:146 +msgid "Colin Law" +msgstr "" + +#: gtk_ardour/about.cc:147 +msgid "Sampo Savolainen" +msgstr "" + +#: gtk_ardour/about.cc:148 +msgid "Joshua Leach" +msgstr "" + +#: gtk_ardour/about.cc:149 +msgid "Rob Holland" +msgstr "" + +#: gtk_ardour/about.cc:150 +msgid "Per Sigmond" +msgstr "" + +#: gtk_ardour/about.cc:151 +msgid "Doug Mclain" +msgstr "" + +#: gtk_ardour/about.cc:156 +msgid "" +"French:\n" +"\tAlain Fréhel " +msgstr "" + +#: gtk_ardour/about.cc:157 +msgid "" +"German:\n" +"\tKarsten Petersen " +msgstr "" + +#: gtk_ardour/about.cc:158 +msgid "" +"Italian:\n" +"\tFilippo Pappalardo " +msgstr "" + +#: gtk_ardour/about.cc:159 +msgid "" +"Portuguese:\n" +"\tRui Nuno Capela " +msgstr "" + +#: gtk_ardour/about.cc:160 +msgid "" +"Brazilian Portuguese:\n" +"\tAlexander da Franca Fernandes \n" +"\tChris Ross " +msgstr "" + +#: gtk_ardour/about.cc:162 +msgid "" +"Spanish:\n" +"\t Alex Krohn " +msgstr "" + +#: gtk_ardour/about.cc:163 +msgid "" +"Russian:\n" +"\t Igor Blinov " +msgstr "" + +#: gtk_ardour/about.cc:181 +#, fuzzy +msgid "" +"Copyright (C) 1999-2005 Paul Davis\n" +"Ardour comes with ABSOLUTELY NO WARRANTY\n" +"This is free software, and you are welcome to redistribute it\n" +"under certain conditions; see the file COPYING for details.\n" +msgstr "" +"Πνευματικά Δικαιώματα (C) 1999-2004 Paul Davis\n" +"Το Ï€ÏόγÏαμμα Ardour διανέμεται δίχως ΑΠΟΛΥΤΩΣ ΚΑΜΙΑ ΕΓΓΥΗΣΗ\n" +"Το παÏόν ειναι δωÏεάν λογισμικό, είστε ευπÏόσδεκτοι να το επαναδιανείμετε \n" +"υπό ειδικοÏÏ‚ ÏŒÏους; διαβάστε το αÏχείο COPYING για λεπτομέÏειες.\n" + +#: gtk_ardour/about.cc:188 +#, fuzzy +msgid "" +"Ardour: %1\n" +"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)" +msgstr "" +"Ardour: %1\n" +"(Κτισμένο με ardour/gtk %2 libardour: %3.%4.%5)" + +#: gtk_ardour/about.cc:206 +msgid "" +"Primary author:\n" +"\tPaul Davis\n" +"\n" +"Major developers:\n" +"\tJesse Chappell\n" +"\tTaybin Rutkin\n" +"Contributors:\n" +"\t" +msgstr "" + +#: gtk_ardour/about.cc:243 +msgid "Authors" +msgstr "ΔημιουÏγοί" + +#: gtk_ardour/about.cc:244 +msgid "Translators" +msgstr "ΜεταφÏαστές" + +#: gtk_ardour/about.cc:361 +msgid "cannot open splash image file \"%1\"" +msgstr "Η εισαγωγική εικόνα δεν ανοίγει\"%1\"" + +#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33 +#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81 +#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977 +#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85 +#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777 +#: gtk_ardour/redirect_box.cc:900 +msgid "OK" +msgstr "OK" + +#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92 +#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046 +#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72 +#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982 +#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733 +#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000 +#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129 +#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785 +#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86 +#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072 +#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33 +#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161 +msgid "Cancel" +msgstr "ΑκÏÏωση" + +#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94 +msgid "Tracks" +msgstr "Κανάλια" + +#: gtk_ardour/add_route_dialog.cc:43 +msgid "Busses" +msgstr "Δίαυλοι" + +#: gtk_ardour/add_route_dialog.cc:48 +msgid "ardour: add track/bus" +msgstr "ardour: Εισαγωγή καναλιοÏ/διαÏλου" + +#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81 +msgid "Add" +msgstr "ΠÏόσθεση" + +#: gtk_ardour/add_route_dialog.cc:86 +msgid "Name (template)" +msgstr "Όνομα (Ï€Ïοσχέδιο)" + +#: gtk_ardour/ardour_ui.cc:798 +msgid "" +"pre\n" +"roll" +msgstr "" +"pre\n" +"roll" + +#: gtk_ardour/ardour_ui.cc:799 +msgid "" +"post\n" +"roll" +msgstr "" +"post\n" +"roll" + +#: gtk_ardour/ardour_ui.cc:807 +msgid "% " +msgstr "% " + +#: gtk_ardour/ardour_ui.cc:808 +msgid "spring" +msgstr "έλασμα" + +#: gtk_ardour/ardour_ui.cc:810 +msgid "" +"punch\n" +"in" +msgstr "" +"punch\n" +"in" + +#: gtk_ardour/ardour_ui.cc:811 +msgid "" +"punch\n" +"out" +msgstr "" +"punch\n" +"out" + +#: gtk_ardour/ardour_ui.cc:812 +msgid "" +"auto\n" +"return" +msgstr "" +"αυτόματη\n" +"επιστÏοφή" + +#: gtk_ardour/ardour_ui.cc:813 +msgid "" +"auto\n" +"play" +msgstr "" +"αυτόματη\n" +"αναπαÏ/γή" + +#: gtk_ardour/ardour_ui.cc:814 +msgid "" +"auto\n" +"input" +msgstr "" +"αυτόματο\n" +"input" + +#: gtk_ardour/ardour_ui.cc:815 +msgid "click" +msgstr "μετÏονόμος" + +#: gtk_ardour/ardour_ui.cc:816 +msgid "" +"follow\n" +"PH" +msgstr "" +"ακολουθία\n" +"ΚεÏσ." + +#: gtk_ardour/ardour_ui.cc:817 +msgid "AUDITIONING" +msgstr "ΑΚΡΟΑΣΗ" + +#: gtk_ardour/ardour_ui.cc:818 +msgid "SOLO" +msgstr "ΣΟΛΟ" + +#: gtk_ardour/ardour_ui.cc:870 +msgid "Percentage" +msgstr "Ποσοστό" + +#: gtk_ardour/ardour_ui.cc:872 +msgid "Semitones" +msgstr "Ημιτόνια" + +#: gtk_ardour/ardour_ui.cc:875 +msgid "Sprung" +msgstr "Έλασμα" + +#: gtk_ardour/ardour_ui.cc:877 +msgid "Wheel" +msgstr "ΤÏοχός" + +#: gtk_ardour/ardour_ui.cc:902 +msgid "" +"You cannot record-enable\n" +"track %1\n" +"because it has no input connections.\n" +"You would be wasting space recording silence." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1073 +msgid "quit" +msgstr "Έξοδος" + +#: gtk_ardour/ardour_ui.cc:1082 +msgid "" +"Ardour was unable to save your session.\n" +"\n" +"If you still wish to quit, please use the\n" +"\n" +"\"Just quit\" option." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1107 +msgid "Save and %1" +msgstr "Αποθήκευση και %1" + +#: gtk_ardour/ardour_ui.cc:1112 +msgid "Just %1" +msgstr "Απλά %1" + +#: gtk_ardour/ardour_ui.cc:1117 +msgid "Don't %1" +msgstr "Μη %1" + +#: gtk_ardour/ardour_ui.cc:1126 +#, fuzzy +msgid "session" +msgstr "ΣυνεδÏία" + +#: gtk_ardour/ardour_ui.cc:1128 +#, fuzzy +msgid "snapshot" +msgstr "Στιγμιότυπο" + +#: gtk_ardour/ardour_ui.cc:1130 +#, fuzzy +msgid "" +"The %1\n" +"\"%2\"\n" +"has not been saved.\n" +"\n" +"Any changes made this time\n" +"will be lost unless you save it.\n" +"\n" +"What do you want to do?" +msgstr "" +"Το Ï„ÏαγοÏδι \"%1\"\n" +"δεν έχει αποθηκευθεί.\n" +"\n" +"Εάν δεν το αποθήκευσετε\n" +"οι αλλαγές που κάνατε θα χαθοÏν.\n" +"\n" +"τί θέλετε να κάνετε;" + +#: gtk_ardour/ardour_ui.cc:1151 +msgid "Prompter" +msgstr "Υποβολέας" + +#: gtk_ardour/ardour_ui.cc:1152 +msgid "ardour: save session?" +msgstr "ardour: αποθήκευση συνεδÏίας;" + +#: gtk_ardour/ardour_ui.cc:1219 +#, fuzzy, c-format +msgid "disconnected" +msgstr "ΑποσÏνδεση" + +#: gtk_ardour/ardour_ui.cc:1226 +#, fuzzy, c-format +msgid "SR: %.1f kHz / %4.1f msecs" +msgstr "SR: %.1f kHz" + +#: gtk_ardour/ardour_ui.cc:1230 +#, c-format +msgid "SR: %u kHz / %4.1f msecs" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1243 +#, c-format +msgid "DSP Load: %.1f%%" +msgstr "ΦοÏτίο DSP: %.1f%%" + +#: gtk_ardour/ardour_ui.cc:1253 +#, c-format +msgid "Disk r:%5.1f w:%5.1f MB/s" +msgstr "Δίσκοι r:%5.1f w:%5.1f MB/s" + +#: gtk_ardour/ardour_ui.cc:1267 +#, fuzzy, c-format +msgid "Buffers p:%%% c:%%%" +msgstr "Buffers p:%5.0f%% c:%5.0f%%" + +#: gtk_ardour/ardour_ui.cc:1294 +msgid "space: 24hrs+" +msgstr "χώÏος : 24hrs+" + +#: gtk_ardour/ardour_ui.cc:1324 +#, c-format +msgid "space: %02dh:%02dm:%02ds" +msgstr "χώÏος: %02dh:%02dm:%02ds" + +#: gtk_ardour/ardour_ui.cc:1575 +msgid "programming error: impossible control method" +msgstr "Σφάλμα Ï€ÏογÏαμματισμοÏ: Μη-πιθανή μέθοδος ελέγχου" + +#: gtk_ardour/ardour_ui.cc:1800 +msgid "cancel" +msgstr "ΑκÏÏωση" + +#: gtk_ardour/ardour_ui.cc:1801 +msgid "rescan" +msgstr "Επανα-ανίχνευση" + +#: gtk_ardour/ardour_ui.cc:1842 +msgid "open session" +msgstr "Άνοιγμα συνεδÏίας" + +#: gtk_ardour/ardour_ui.cc:1897 +msgid "Patience is a virtue.\n" +msgstr "Η Υπομονή ειναι ΧÏυσός.\n" + +#: gtk_ardour/ardour_ui.cc:1906 +msgid "You cannot add a track without a session already loaded." +msgstr "Δεν γίνεται να Ï€Ïοστεθεί κανάλι χωÏίς ήδη φοÏτωμένη συνεδÏία." + +#: gtk_ardour/ardour_ui.cc:1913 +msgid "could not create new audio track" +msgstr "Δεν γίνεται να δημιουÏγηθεί νέο ηχητικό κανάλι" + +#: gtk_ardour/ardour_ui.cc:1917 +msgid "could not create new audio bus" +msgstr "Δεν γίνεται να δημιουÏγηθεί νέος ηχητικός δίαυλος" + +#: gtk_ardour/ardour_ui.cc:1936 +msgid "" +"There are insufficient JACK ports available\n" +"to create a new track or bus.\n" +"You should save Ardour, exit and\n" +"restart JACK with more ports." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2071 +msgid "" +"Please create 1 or more track\n" +"before trying to record.\n" +"Check the Session menu." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2312 +#, fuzzy +msgid "" +"JACK has either been shutdown or it\n" +"disconnected Ardour because Ardour\n" +"was not fast enough. You can save the\n" +"session and/or try to reconnect to JACK ." +msgstr "" +"Ή ο JACK απενεÏγοποιήθηκε ή αυτός\n" +"αποσÏνδεσε το Ardour διότι το Ardour\n" +"δεν ήταν αÏκετά γÏήγοÏο. ΚαλÏτεÏα να αποθηκεÏσετε τη\n" +"συνεδÏία και να επανακινήσετε και τον JACK και το Ardour." + +#: gtk_ardour/ardour_ui.cc:2328 +msgid "Unable to create all required ports" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2336 +#, fuzzy +msgid "Unable to start the session running" +msgstr "ΑÏχή της συνεδÏίας" + +#: gtk_ardour/ardour_ui.cc:2472 +msgid "No Stream" +msgstr "Δεν υπάÏχει Ïοή(No stream)" + +#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518 +msgid "none" +msgstr "Κανένα" + +#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527 +#: gtk_ardour/automation_time_axis.cc:189 +#: gtk_ardour/automation_time_axis.cc:218 +#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211 +#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947 +#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659 +msgid "off" +msgstr "εκτός" + +#: gtk_ardour/ardour_ui.cc:2548 +msgid "Name for snapshot" +msgstr "Όνομα για στιγμιότυπο" + +#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294 +msgid "Name for mix template:" +msgstr "Όνομα για Ï€Ïοσχεδίο μίξεως:" + +#: gtk_ardour/ardour_ui.cc:2717 +msgid "-template" +msgstr "-Ï€Ïοσχέδιο" + +#: gtk_ardour/ardour_ui.cc:2760 +msgid "Session %1 already exists at %2" +msgstr "Η ΣυνεδÏία %1 υπάÏχει ήδη στο %2" + +#: gtk_ardour/ardour_ui.cc:2832 +msgid "" +"You do not have write access to this session.\n" +"This prevents the session from being loaded." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897 +msgid "Session \"%1 (snapshot %2)\" did not load successfully" +msgstr "Η ΣυνεδÏία \"%1 (στιγμιότυπο %2)\" δεν φοÏτώθηκε επιτυχώς" + +#: gtk_ardour/ardour_ui.cc:2966 +msgid "" +"No audio files were ready for cleanup\n" +"\n" +"If this seems suprising, check for any existing\n" +"snapshots. These may still include regions that\n" +"require some unused files to continue to exist." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001 +msgid "files" +msgstr "αÏχεία" + +#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003 +msgid "file" +msgstr "αÏχείο" + +#: gtk_ardour/ardour_ui.cc:3026 +msgid "ardour: cleanup" +msgstr "ardour: εκκαθάÏιση" + +#: gtk_ardour/ardour_ui.cc:3040 +msgid "" +"Cleanup is a destructive operation.\n" +"ALL undo/redo information will be lost if you cleanup.\n" +"Unused audio files will be moved to a \"dead sounds\" location." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3045 +msgid "Proceed with cleanup" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3061 +#, fuzzy +msgid "CleanupDialog" +msgstr "ΕκκαθάÏιση" + +#: gtk_ardour/ardour_ui.cc:3062 +#, fuzzy +msgid "ardour cleanup" +msgstr "ardour: εκκαθάÏιση" + +#: gtk_ardour/ardour_ui.cc:3063 +#, fuzzy +msgid "ardour_cleanup" +msgstr "ardour: εκκαθάÏιση" + +#: gtk_ardour/ardour_ui.cc:3086 +msgid "cleaned files" +msgstr "καθαÏισμένα αÏχεία" + +#: gtk_ardour/ardour_ui.cc:3087 +msgid "" +"The following %1 %2 were not in use.\n" +"The next time you flush the wastebasket\n" +"it will release an additional %3 %4bytes\n" +"of disk space" +msgstr "" +"Τα ακόλουθα %1 %2 δεν χÏησιμοποιοÏνταν.\n" +"Την επόμενη φοÏά που θα αδειάσετε τον κάδο\n" +"θα ελευθεÏωθοÏν %3 %4bytes\n" +"χώÏου στο δίσκο" + +#: gtk_ardour/ardour_ui.cc:3110 +msgid "deleted file" +msgstr "διαγÏαμμένα αÏχεία" + +#: gtk_ardour/ardour_ui.cc:3111 +msgid "" +"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space" +msgstr "" +"Τα ακόλουθα %1 file%2 διεγÏάφησαν, ελευθεÏώνοντας %3 %4bytes χώÏου στο δίσκο" + +#: gtk_ardour/ardour_ui.cc:3226 +msgid "Recording was stopped because your system could not keep up." +msgstr "η ΕγγÏαφή διεκόπη διότι το σÏστημά δεν μποÏοÏσε να ανταπεξέλθει." + +#: gtk_ardour/ardour_ui.cc:3248 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to write data to disk\n" +"quickly enough to keep up with recording.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3266 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to read data from disk\n" +"quickly enough to keep up with playback.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3291 +msgid "Recover from crash" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3292 +msgid "Ignore crash data" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3293 +msgid "" +"This session appears to have been in\n" +"middle of recording when ardour or\n" +"the computer was shutdown.\n" +"\n" +"Ardour can recover any captured audio for\n" +"you, or it can ignore it. Please decide\n" +"what you would like to do.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3338 +#, fuzzy +msgid "Could not disconnect from JACK" +msgstr "Δεν γινόταν να συνδεθώ στον JACK server σαν \"%1\"" + +#: gtk_ardour/ardour_ui.cc:3351 +#, fuzzy +msgid "Could not reconnect to JACK" +msgstr "Δεν γινόταν να συνδεθώ στον JACK server σαν \"%1\"" + +#: gtk_ardour/ardour_ui2.cc:60 +msgid "UI: cannot setup editor" +msgstr "UI: Ο 'editor' δεν μποÏεί να εγεÏθεί" + +#: gtk_ardour/ardour_ui2.cc:65 +msgid "UI: cannot setup mixer" +msgstr "UI: ο μίκτης δεν μποÏεί να εγεÏθεί" + +#: gtk_ardour/ardour_ui2.cc:70 +msgid "UI: cannot setup meter_bridge" +msgstr "UI: η γέφυÏα μετÏήσεων δεν μποÏεί να εγεÏθεί" + +#: gtk_ardour/ardour_ui2.cc:98 +msgid "MMC + Local" +msgstr "MMC + Τοπικό" + +#: gtk_ardour/ardour_ui2.cc:99 +msgid "MMC" +msgstr "MMC" + +#: gtk_ardour/ardour_ui2.cc:100 +msgid "Local" +msgstr "Τοπικό" + +#: gtk_ardour/ardour_ui2.cc:117 +msgid "MMC ID" +msgstr "MMC ID" + +#: gtk_ardour/ardour_ui2.cc:215 +msgid "Play from playhead" +msgstr "ΑναπαÏ/γή από τον ΑναπαÏαγωγέα" + +#: gtk_ardour/ardour_ui2.cc:216 +msgid "Stop playback" +msgstr "Διακοπή ΑναπαÏ/γής" + +#: gtk_ardour/ardour_ui2.cc:217 +msgid "Play range/selection" +msgstr "ΑναπαÏ/γή διαστήματος/επιλογής" + +#: gtk_ardour/ardour_ui2.cc:218 +msgid "Go to start of session" +msgstr "ΑÏχή της συνεδÏίας" + +#: gtk_ardour/ardour_ui2.cc:219 +msgid "Go to end of session" +msgstr "Τέλος του συνεδÏίας" + +#: gtk_ardour/ardour_ui2.cc:220 +msgid "Play loop range" +msgstr "Επαναληπτική αναπαÏ/γή διαστήματος" + +#: gtk_ardour/ardour_ui2.cc:221 +msgid "Return to last playback start when stopped" +msgstr "ΕπιστÏοφή στην τελευταία θεση μετα απο παÏση" + +#: gtk_ardour/ardour_ui2.cc:222 +msgid "Start playback after any locate" +msgstr "ΑÏχή αναπαÏ/γής μετά από κάθε τοποθέτηση" + +#: gtk_ardour/ardour_ui2.cc:223 +msgid "Be sensible about input monitoring" +msgstr "ΠÏοσοχή στο input monitoring" + +#: gtk_ardour/ardour_ui2.cc:224 +msgid "Start recording at auto-punch start" +msgstr "ΈναÏξη εγγÏαφής στην αÏχή αυτο-εναπόθεσης" + +#: gtk_ardour/ardour_ui2.cc:225 +msgid "Stop recording at auto-punch end" +msgstr "Λήξη εγγÏαφής στο τέλος αυτο-εναπόθεσης" + +#: gtk_ardour/ardour_ui2.cc:226 +msgid "Enable/Disable audio click" +msgstr "ΆÏση/ΠαÏση μετÏονόμου" + +#: gtk_ardour/ardour_ui2.cc:227 +msgid "Enable/Disable follow playhead" +msgstr "ΆÏση/ΠαÏση ακολουθίας αναπαÏαγωγέα" + +#: gtk_ardour/ardour_ui2.cc:228 +msgid "Shuttle speed control" +msgstr "Έλεγχος ταχÏτητας Shuttle" + +#: gtk_ardour/ardour_ui2.cc:229 +#, fuzzy, c-format +msgid "Select semitones or %%-age for speed display" +msgstr "Επιλογή ημιτονίων ή %- για απεικόνιση ταχÏτητος" + +#: gtk_ardour/ardour_ui2.cc:230 +msgid "Select sprung or wheel behaviour" +msgstr "Επιλογή συμπεÏιφοÏάς ελάσματος ή Ï„ÏοχοÏ" + +#: gtk_ardour/ardour_ui2.cc:231 +msgid "Current transport speed" +msgstr "ΤÏέχουσα ταχÏτητα μεταφοÏάς" + +#: gtk_ardour/ardour_ui2.cc:312 +msgid "Primary clock" +msgstr "ΠÏωτεÏον ωÏολόγιον" + +#: gtk_ardour/ardour_ui2.cc:313 +msgid "secondary clock" +msgstr "ΔευτεÏέυον ωÏολόγιον" + +#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751 +#: gtk_ardour/ardour_ui2.cc:770 +msgid "stopped" +msgstr "παÏση" + +#: gtk_ardour/ardour_ui2.cc:431 +msgid "ardour: clock" +msgstr "ardour: ΩÏολόγιον" + +#: gtk_ardour/ardour_ui2.cc:721 +msgid "st" +msgstr "st" + +#: gtk_ardour/ardour_ui2.cc:731 +msgid "sprung" +msgstr "έλασμα" + +#: gtk_ardour/ardour_ui2.cc:742 +msgid "wheel" +msgstr "Ï„Ïοχός" + +#: gtk_ardour/ardour_ui_dependents.cc:74 +msgid "keyboard_target: error setting binding state: invalid node" +msgstr "" +"keyboard_target: σφάλμα στη θέση καταστάσεως Î´ÎµÏƒÎ¼Î¿Ï Ï€Î»Î®ÎºÏ„Ïων: ανÏπαÏκτος " +"κόμβος" + +#: gtk_ardour/ardour_ui_dialogs.cc:158 +msgid "close session" +msgstr "κλείσιμο συνεδÏίας" + +#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895 +msgid "New" +msgstr "Îέο" + +#: gtk_ardour/ardour_ui_ed.cc:76 +msgid "Open" +msgstr "Άνοιγμα" + +#: gtk_ardour/ardour_ui_ed.cc:77 +msgid "Recent" +msgstr "ΠÏόσφατο" + +#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +msgid "Close" +msgstr "Κλείσιμο" + +#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488 +msgid "Add Track/Bus" +msgstr "ΠÏόσθεση καναλιοÏ/διαÏλου" + +#: gtk_ardour/ardour_ui_ed.cc:99 +msgid "Connect" +msgstr "ΣÏνδεση" + +#: gtk_ardour/ardour_ui_ed.cc:100 +msgid "Image Compositor" +msgstr "ΣÏνθεση εικόνων" + +#: gtk_ardour/ardour_ui_ed.cc:114 +msgid "Save" +msgstr "Αποθήκευση" + +#: gtk_ardour/ardour_ui_ed.cc:118 +msgid "Snapshot" +msgstr "Στιγμιότυπο" + +#: gtk_ardour/ardour_ui_ed.cc:126 +msgid "Save Template..." +msgstr "Αποθήκευση Ï€Ïοσχεδίου..." + +#: gtk_ardour/ardour_ui_ed.cc:133 +msgid "Export session to audiofile..." +msgstr "Εξαγωγή συνεδÏίας σε αÏχείο..." + +#: gtk_ardour/ardour_ui_ed.cc:134 +msgid "Export range to audiofile..." +msgstr "Εξαγωγή διαστήματος σε αÏχείο..." + +#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312 +#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118 +#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227 +msgid "Export" +msgstr "Εξαγωγή" + +#: gtk_ardour/ardour_ui_ed.cc:146 +msgid "Cleanup unused sources" +msgstr "ΕκκαθάÏιση αχÏήστων πηγών" + +#: gtk_ardour/ardour_ui_ed.cc:147 +msgid "Flush wastebasket" +msgstr "Άδειασμα κάδου" + +#: gtk_ardour/ardour_ui_ed.cc:149 +msgid "Cleanup" +msgstr "ΕκκαθάÏιση" + +#: gtk_ardour/ardour_ui_ed.cc:154 +msgid "Quit" +msgstr "Έξοδος" + +#: gtk_ardour/ardour_ui_ed.cc:156 +msgid "Session" +msgstr "ΣυνεδÏία" + +#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287 +#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499 +#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570 +#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412 +msgid "Edit" +msgstr "ΕπεξεÏγασία" + +#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572 +#: gtk_ardour/mixer_strip.cc:631 +msgid "Disconnect" +msgstr "ΑποσÏνδεση" + +#: gtk_ardour/ardour_ui_ed.cc:174 +#, fuzzy +msgid "Reconnect" +msgstr "ΣÏνδεση" + +#: gtk_ardour/ardour_ui_ed.cc:192 +msgid "Latency" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:195 +msgid "JACK" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:205 +msgid "Editor" +msgstr "ΕπεξεÏγαστής" + +#: gtk_ardour/ardour_ui_ed.cc:206 +msgid "Mixer" +msgstr "Μίκτης" + +#: gtk_ardour/ardour_ui_ed.cc:212 +msgid "Options Editor" +msgstr "Επεξ/στης Ρυθμίσεων" + +#: gtk_ardour/ardour_ui_ed.cc:219 +msgid "Audio Library" +msgstr "Ηχητική βιβλιοθήκη" + +#: gtk_ardour/ardour_ui_ed.cc:225 +#, fuzzy +msgid "Track/Bus Inspector" +msgstr "κανάλια/δίαυλοι" + +#: gtk_ardour/ardour_ui_ed.cc:232 +msgid "Connections" +msgstr "Συνδέσεις" + +#: gtk_ardour/ardour_ui_ed.cc:240 +msgid "Meter Bridge" +msgstr "ΓέφυÏα μετÏητή" + +#: gtk_ardour/ardour_ui_ed.cc:248 +msgid "Locations" +msgstr "Τοποθεσίες" + +#: gtk_ardour/ardour_ui_ed.cc:255 +msgid "Big Clock" +msgstr "Μεγάλο ωÏολόγιον" + +#: gtk_ardour/ardour_ui_ed.cc:261 +msgid "About" +msgstr "ΠληÏοφοÏίες" + +#: gtk_ardour/ardour_ui_ed.cc:264 +msgid "Windows" +msgstr "ΠαÏάθυÏα" + +#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203 +msgid "SMPTE" +msgstr "SMPTE" + +#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202 +#: gtk_ardour/editor_rulers.cc:359 +msgid "Bars:Beats" +msgstr "ΜπάÏες:ΚτÏποι" + +#: gtk_ardour/audio_clock.cc:1642 +msgid "Minutes:Seconds" +msgstr "Λεπτά:ΔεÏτεÏα" + +#: gtk_ardour/audio_clock.cc:1643 +msgid "Audio Frames" +msgstr "Ηχητικά frames" + +#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356 +#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713 +#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774 +#: gtk_ardour/option_editor.cc:794 +msgid "Off" +msgstr "Εκτός" + +#: gtk_ardour/audio_clock.cc:1646 +msgid "Mode" +msgstr "ΛειτουÏγία" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523 +msgid "m" +msgstr "m" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524 +msgid "s" +msgstr "s" + +#: gtk_ardour/audio_time_axis.cc:104 +msgid "r" +msgstr "r" + +#: gtk_ardour/audio_time_axis.cc:108 +msgid "g" +msgstr "g" + +#: gtk_ardour/audio_time_axis.cc:109 +msgid "p" +msgstr "p" + +#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44 +#: gtk_ardour/visual_time_axis.cc:90 +msgid "h" +msgstr "h" + +#: gtk_ardour/audio_time_axis.cc:111 +msgid "a" +msgstr "a" + +#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89 +msgid "v" +msgstr "v" + +#: gtk_ardour/audio_time_axis.cc:185 +msgid "Record" +msgstr "ΕγγÏαφή" + +#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191 +msgid "Solo" +msgstr "Σόλο" + +#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236 +#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433 +msgid "Mute" +msgstr "Σιγή" + +#: gtk_ardour/audio_time_axis.cc:188 +msgid "Edit Group" +msgstr "ΔιαμόÏφωση Ομάδας" + +#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110 +msgid "Display Height" +msgstr "Απεικόνιση Ïψους" + +#: gtk_ardour/audio_time_axis.cc:190 +msgid "Playlist" +msgstr "Playlist" + +#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752 +msgid "Automation" +msgstr "Αυτοματισμός" + +#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111 +msgid "Visual options" +msgstr "Επιλογές Εμφανίσεως" + +#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112 +msgid "Hide this track" +msgstr "ΑπόκÏυψη παÏόντος καναλιοÏ" + +#: gtk_ardour/audio_time_axis.cc:349 +msgid "No group" +msgstr "ΧωÏίς ομάδα" + +#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447 +#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229 +msgid "Height" +msgstr "Ύψος" + +#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266 +#: gtk_ardour/marker_time_axis.cc:230 +msgid "Color" +msgstr "ΧÏώμα" + +#: gtk_ardour/audio_time_axis.cc:720 +msgid "Hide all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:721 +msgid "Show all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:729 +msgid "show all automation" +msgstr "Ανάδειξη όλων των αυτοματισμών" + +#: gtk_ardour/audio_time_axis.cc:732 +msgid "show existing automation" +msgstr "Ανάδειξη υπαÏχόντων αυτοματισμών" + +#: gtk_ardour/audio_time_axis.cc:735 +msgid "hide all automation" +msgstr "ΚÏÏψιμο όλων των αυτοματισμών" + +#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204 +#: gtk_ardour/editor.cc:234 +msgid "gain" +msgstr "gain" + +#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244 +msgid "pan" +msgstr "pan" + +#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388 +msgid "Plugins" +msgstr "Plugins" + +#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95 +msgid "Show waveforms" +msgstr "Ανάδειξη κυματομοÏφών" + +#: gtk_ardour/audio_time_axis.cc:766 +msgid "Traditional" +msgstr "ΠαÏαδοσιακή" + +#: gtk_ardour/audio_time_axis.cc:769 +msgid "Rectified" +msgstr "ΑνοÏθωμένή" + +#: gtk_ardour/audio_time_axis.cc:772 +msgid "Waveform" +msgstr "ΚυματομοÏφή" + +#: gtk_ardour/audio_time_axis.cc:782 +#, fuzzy +msgid "align with existing material" +msgstr "ΥπάÏχον υλικό" + +#: gtk_ardour/audio_time_axis.cc:787 +#, fuzzy +msgid "align with capture time" +msgstr "ΧÏόνος Λήψεως" + +#: gtk_ardour/audio_time_axis.cc:793 +#, fuzzy +msgid "Alignment" +msgstr "ΕυθυγÏάμμιση" + +#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288 +msgid "Active" +msgstr "ΕνεÏγό" + +#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386 +#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467 +#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269 +#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233 +#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83 +msgid "Remove" +msgstr "Απαλοιφή" + +#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880 +#: gtk_ardour/audio_time_axis.cc:911 +msgid "Name for playlist" +msgstr "Όνομα για playlist" + +#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433 +msgid "a track already exists with that name" +msgstr "Κανάλι με αυτό το όνομα ήδη υπάÏχει" + +#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001 +#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539 +msgid "programming error: " +msgstr "σφάλμα Ï€ÏογÏαμματισμοÏ: " + +#: gtk_ardour/audio_time_axis.cc:1889 +msgid "Current: %1" +msgstr "ΤÏέχον: %1" + +#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452 +#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226 +#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377 +msgid "Rename" +msgstr "Μετονομασία" + +#: gtk_ardour/audio_time_axis.cc:1896 +msgid "New Copy" +msgstr "Îέο αντίγÏαφο" + +#: gtk_ardour/audio_time_axis.cc:1898 +msgid "Clear Current" +msgstr "ΕκκαθάÏιση Ï„Ïέχοντος" + +#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472 +#: gtk_ardour/editor.cc:2557 +msgid "Select" +msgstr "Επιλογή" + +#: gtk_ardour/automation_line.cc:904 +msgid "automation event move" +msgstr "μετακίνηση συμβάντος αυτοματισμοÏ" + +#: gtk_ardour/automation_line.cc:906 +msgid "automation range drag" +msgstr "έλξη διαστήματος αυτοματισμοÏ" + +#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64 +msgid "remove control point" +msgstr "απαλοιφή σημείου ελέγχου" + +#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010 +msgid "clear" +msgstr "εκκαθάÏιση" + +#: gtk_ardour/automation_time_axis.cc:80 +msgid "track height" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:81 +#, fuzzy +msgid "automation state" +msgstr "Κατάσταση Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï pan" + +#: gtk_ardour/automation_time_axis.cc:82 +#, fuzzy +msgid "clear track" +msgstr "διαγÏαφή διαστημάτων" + +#: gtk_ardour/automation_time_axis.cc:83 +#, fuzzy +msgid "hide track" +msgstr "νÏξη καναλιοÏ" + +#: gtk_ardour/automation_time_axis.cc:191 +#: gtk_ardour/automation_time_axis.cc:229 +#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213 +#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419 +#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50 +msgid "play" +msgstr "αναπαÏαγωγή" + +#: gtk_ardour/automation_time_axis.cc:193 +#: gtk_ardour/automation_time_axis.cc:240 +#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215 +#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422 +#: gtk_ardour/plugin_ui.cc:663 +msgid "write" +msgstr "εγγÏαφή" + +#: gtk_ardour/automation_time_axis.cc:195 +#: gtk_ardour/automation_time_axis.cc:251 +#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217 +#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953 +#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665 +msgid "touch" +msgstr "άγγιγμα" + +#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274 +#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428 +msgid "???" +msgstr "???" + +#: gtk_ardour/automation_time_axis.cc:276 +msgid "clear automation" +msgstr "εκκαθάÏιση αυτοματισμοÏ" + +#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453 +#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398 +msgid "Hide" +msgstr "ΚÏÏψιμο" + +#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52 +#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364 +msgid "Clear" +msgstr "ΕκκαθάÏιση" + +#: gtk_ardour/automation_time_axis.cc:474 +#, fuzzy +msgid "State" +msgstr "ΑÏχή:" + +#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49 +msgid "Input Connections" +msgstr "Συνδέσεις Εισόδου" + +#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48 +msgid "Output Connections" +msgstr "Συνδέσεις Εξόδου" + +#: gtk_ardour/connection_editor.cc:49 +#, fuzzy +msgid "New Input" +msgstr "νέα είσοδος" + +#: gtk_ardour/connection_editor.cc:50 +#, fuzzy +msgid "New Output" +msgstr "νέα έξοδος" + +#: gtk_ardour/connection_editor.cc:51 +#, fuzzy +msgid "Delete" +msgstr "διαγÏαφή" + +#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96 +#, fuzzy +msgid "Add Port" +msgstr "Ï€Ïόσθεση θÏÏας" + +#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105 +#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786 +#, fuzzy +msgid "Rescan" +msgstr "Επανα-ανίχνευση" + +#: gtk_ardour/connection_editor.cc:101 +msgid "Available Ports" +msgstr "Διαθέσιμες ΘÏÏες" + +#: gtk_ardour/connection_editor.cc:183 +msgid "ardour: connections" +msgstr "ardour: συνδέσεις" + +#: gtk_ardour/connection_editor.cc:513 +#, c-format +msgid "in %d" +msgstr "σε %d" + +#: gtk_ardour/connection_editor.cc:644 +msgid "Name for new connection:" +msgstr "Όνομα για νέα σÏνδεση:" + +#: gtk_ardour/crossfade_edit.cc:71 +#, fuzzy +msgid "crossfade editor" +msgstr "επεξεÏ/σία fade in" + +#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449 +#, fuzzy +msgid "Reset" +msgstr "reset" + +#: gtk_ardour/crossfade_edit.cc:78 +#, fuzzy +msgid "Fade" +msgstr "Fades" + +#: gtk_ardour/crossfade_edit.cc:79 +#, fuzzy +msgid "Out (dry)" +msgstr "out (dry)" + +#: gtk_ardour/crossfade_edit.cc:80 +#, fuzzy +msgid "Out" +msgstr "Έξοδοι" + +#: gtk_ardour/crossfade_edit.cc:81 +#, fuzzy +msgid "In (dry)" +msgstr "in (dry)" + +#: gtk_ardour/crossfade_edit.cc:82 +msgid "In" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:84 +#, fuzzy +msgid "With Pre-roll" +msgstr "με pre-roll" + +#: gtk_ardour/crossfade_edit.cc:85 +#, fuzzy +msgid "With Post-roll" +msgstr "με post-roll" + +#: gtk_ardour/crossfade_edit.cc:93 +msgid "Fade In" +msgstr "Fade In" + +#: gtk_ardour/crossfade_edit.cc:94 +msgid "Fade Out" +msgstr "Fade Out" + +#: gtk_ardour/crossfade_edit.cc:98 +msgid "ardour: x-fade edit" +msgstr "ardour: επεξεÏγασία x-fade" + +#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311 +#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189 +msgid "Audition" +msgstr "ΑκÏόαση" + +#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804 +msgid "Regions/name" +msgstr "ΠεÏιοχες/όνομα" + +#: gtk_ardour/editor.cc:108 +msgid "Chunks" +msgstr "Κομμάτια" + +#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079 +msgid "Slide" +msgstr "Ολίσθηση" + +#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077 +msgid "Splice" +msgstr "Splice" + +#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136 +#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96 +#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977 +msgid "None" +msgstr "Ουδέν" + +#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124 +#, fuzzy +msgid "CD Frames" +msgstr "Frames" + +#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126 +msgid "SMPTE Frames" +msgstr "SMPTE Frames" + +#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128 +msgid "SMPTE Seconds" +msgstr "SMPTE ΔευτεÏόλεπτα" + +#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130 +msgid "SMPTE Minutes" +msgstr "SMPTE Λεπτά" + +#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132 +msgid "Seconds" +msgstr "ΔευτεÏόλεπτα" + +#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134 +msgid "Minutes" +msgstr "Λεπτά" + +#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106 +msgid "Beats/32" +msgstr "ΚτÏποι/32" + +#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104 +msgid "Beats/16" +msgstr "ΚτÏποι/16" + +#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102 +msgid "Beats/8" +msgstr "ΚτÏποι/8" + +#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100 +msgid "Beats/4" +msgstr "ΚτÏποι/4" + +#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098 +msgid "Beats/3" +msgstr "ΚτÏποι/3" + +#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108 +msgid "Beats" +msgstr "ΚτÏποι" + +#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110 +msgid "Bars" +msgstr "ΜπάÏες" + +#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112 +msgid "Marks" +msgstr "Στίγματα" + +#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114 +#: gtk_ardour/editor.cc:4182 +msgid "Edit Cursor" +msgstr "ΚέÏσοÏας επεξεÏγασίας" + +#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116 +msgid "Region starts" +msgstr "ΑÏχές ΠεÏιοχών" + +#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118 +msgid "Region ends" +msgstr "Τέλη ΠεÏιοχών" + +#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122 +msgid "Region syncs" +msgstr "ΣυγχÏονισμός ΠεÏιοχών" + +#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120 +msgid "Region bounds" +msgstr "ÎŒÏια πεÏιοχών" + +#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153 +#: gtk_ardour/time_axis_view.cc:449 +msgid "Normal" +msgstr "Κανονικό" + +#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155 +msgid "Magnetic" +msgstr "Μαγνητικό" + +#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174 +#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237 +msgid "Left" +msgstr "ΑÏιστεÏÏŒ" + +#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176 +#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238 +msgid "Right" +msgstr "Δεξιό" + +#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178 +msgid "Center" +msgstr "ΚέντÏο" + +#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180 +msgid "Playhead" +msgstr "ΑναπαÏαγωγέας" + +#: gtk_ardour/editor.cc:201 +msgid "Mins:Secs" +msgstr "Λεπτά:ΔέυτεÏα" + +#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353 +msgid "Frames" +msgstr "Frames" + +#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373 +msgid "Tempo" +msgstr "ΧÏόνος" + +#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367 +msgid "Meter" +msgstr "ΜετÏητής" + +#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379 +msgid "Location Markers" +msgstr "Στίγματα Τοποθεσίας" + +#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385 +msgid "Range Markers" +msgstr "Στίγματα διαστημάτων" + +#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391 +msgid "Loop/Punch Ranges" +msgstr "Διαστήματα Loop/Punch" + +#: gtk_ardour/editor.cc:221 +msgid "" +"editor\n" +"mixer" +msgstr "" +"Μίκτης\n" +"ΕπεξεÏγαστή" + +#: gtk_ardour/editor.cc:232 +msgid "range" +msgstr "διάστημα" + +#: gtk_ardour/editor.cc:233 +msgid "object" +msgstr "αντικείμενο" + +#: gtk_ardour/editor.cc:235 +msgid "zoom" +msgstr "zoom" + +#: gtk_ardour/editor.cc:236 +msgid "timefx" +msgstr "timefx" + +#: gtk_ardour/editor.cc:237 +#, fuzzy +msgid "listen" +msgstr "link" + +#: gtk_ardour/editor.cc:239 +msgid "mode" +msgstr "λειτουÏγία" + +#: gtk_ardour/editor.cc:240 +msgid "automation" +msgstr "αυτοματισμός" + +#: gtk_ardour/editor.cc:242 +msgid "Edit Mode" +msgstr "ΛειτουÏγία Επεξ/σίας" + +#: gtk_ardour/editor.cc:243 +msgid "Snap To" +msgstr "Έλξη σε" + +#: gtk_ardour/editor.cc:244 +msgid "Snap Mode" +msgstr "ΛειτουÏγία Έλξεως" + +#: gtk_ardour/editor.cc:245 +msgid "Zoom Focus" +msgstr "Εστίαση Zoom" + +#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364 +#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579 +msgid "Nudge" +msgstr "ÎÏξη" + +#: gtk_ardour/editor.cc:511 +msgid "Zoom in" +msgstr "Zoom in" + +#: gtk_ardour/editor.cc:512 +msgid "Zoom out" +msgstr "Zoom out" + +#: gtk_ardour/editor.cc:517 +msgid "Zoom to session" +msgstr "Zoom στη συνεδÏία" + +#: gtk_ardour/editor.cc:536 +msgid "Zoom Span" +msgstr "ΕÏÏος Zoom" + +#: gtk_ardour/editor.cc:566 +msgid "Edit Groups" +msgstr "ΠÏόσθεση Ομάδων" + +#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142 +msgid "-all-" +msgstr "-όλα-" + +#: gtk_ardour/editor.cc:718 +msgid "Nudge region/selection forwards" +msgstr "ÎÏξη πεÏιοχής/επιλογής εμπÏός" + +#: gtk_ardour/editor.cc:719 +msgid "Nudge region/selection backwards" +msgstr "ÎÏξη πεÏιοχής/επιλογής πίσω" + +#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308 +msgid "ardour: editor" +msgstr "ardour: επεξεÏγαστής" + +#: gtk_ardour/editor.cc:729 +msgid "ardour_editor" +msgstr "ardour_επεξεÏγαστής" + +#: gtk_ardour/editor.cc:846 +msgid "VerboseCanvasCursor" +msgstr "" + +#: gtk_ardour/editor.cc:1405 +msgid "FirstActionMessage" +msgstr "" + +#: gtk_ardour/editor.cc:1407 +msgid "Start a new session\n" +msgstr "ΑÏχή καινοÏÏιας συνεδÏίας\n" + +#: gtk_ardour/editor.cc:1408 +msgid "via Session menu" +msgstr "μέσω του Î¼ÎµÎ½Î¿Ï Î£Ï…Î½ÎµÎ´Ïίας" + +#: gtk_ardour/editor.cc:1703 +msgid "ardour: editor: " +msgstr "ardour: επεξεÏγαστής: " + +#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796 +#: gtk_ardour/editor_markers.cc:797 +msgid "Loop" +msgstr "Loop" + +#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810 +#: gtk_ardour/editor_markers.cc:823 +msgid "Punch" +msgstr "Punch" + +#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688 +msgid "programming error: fade in canvas item has no regionview data pointer!" +msgstr "" +"Σφάλμα Ï€ÏογÏαμματισμοÏ: το αντικείμενο 'fade in canvas' δεν διαθέτει δείκτη " +"δεδομένων οπτικής πεÏιοχών!" + +#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986 +#: gtk_ardour/redirect_box.cc:401 +msgid "Deactivate" +msgstr "ΑπενεÏγοποίηση" + +#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988 +#: gtk_ardour/redirect_box.cc:398 +msgid "Activate" +msgstr "ΕνεÏγοποίηση" + +#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993 +msgid "Linear" +msgstr "ΓÏαμμικό" + +#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994 +#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734 +#: gtk_ardour/option_editor.cc:796 +msgid "Slowest" +msgstr "ΑÏγότατο" + +#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995 +#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735 +#: gtk_ardour/option_editor.cc:798 +msgid "Slow" +msgstr "ΑÏγό" + +#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996 +#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737 +#: gtk_ardour/option_editor.cc:802 +msgid "Fast" +msgstr "ΤαχÏ" + +#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997 +#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739 +#: gtk_ardour/option_editor.cc:806 +msgid "Fastest" +msgstr "ΤαχÏτατο" + +#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113 +msgid "Freeze" +msgstr "Πάγωμα" + +#: gtk_ardour/editor.cc:2109 +msgid "Unfreeze" +msgstr "Ξεπάγωμα" + +#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328 +#, fuzzy +msgid "Unmute" +msgstr "σιγή" + +#: gtk_ardour/editor.cc:2247 +msgid "Convert to short" +msgstr "" + +#: gtk_ardour/editor.cc:2249 +msgid "Convert to full" +msgstr "" + +#: gtk_ardour/editor.cc:2260 +#, fuzzy +msgid "Crossfade" +msgstr "Crossfade" + +#: gtk_ardour/editor.cc:2303 +msgid "Popup region editor" +msgstr "Εμφάνιση του Ïυθμιστή πεÏιοχής" + +#: gtk_ardour/editor.cc:2304 +#, fuzzy +msgid "Raise to top layer" +msgstr "ΑνόÏθωση πεÏιοχής στο ανώτατο στÏώμα" + +#: gtk_ardour/editor.cc:2305 +#, fuzzy +msgid "Lower to bottom layer" +msgstr "Υποβίβαση πεÏιοχής στο κατώτατο στÏώμα" + +#: gtk_ardour/editor.cc:2307 +msgid "Define sync point" +msgstr "ΠÏοσδιοÏισμός σημείου συγχÏονισμοÏ" + +#: gtk_ardour/editor.cc:2308 +msgid "Remove sync point" +msgstr "Απαλοιφή σημείου συγχÏονισμοÏ" + +#: gtk_ardour/editor.cc:2313 +#, fuzzy +msgid "Bounce" +msgstr "Αναπήδηση διαστήματος" + +#: gtk_ardour/editor.cc:2323 +msgid "Lock" +msgstr "Κλείδωμα" + +#: gtk_ardour/editor.cc:2324 +msgid "Unlock" +msgstr "Ξεκλείδωμα" + +#: gtk_ardour/editor.cc:2334 +msgid "Original position" +msgstr "ΠÏωταÏχική θέση" + +#: gtk_ardour/editor.cc:2340 +msgid "Toggle envelope visibility" +msgstr "" + +#: gtk_ardour/editor.cc:2341 +#, fuzzy +msgid "Toggle envelope active" +msgstr "Διακόπτης ΕνεÏγοÏ" + +#: gtk_ardour/editor.cc:2345 +#, fuzzy +msgid "DeNormalize" +msgstr "Εξομάλυνση" + +#: gtk_ardour/editor.cc:2347 +msgid "Normalize" +msgstr "Εξομάλυνση" + +#: gtk_ardour/editor.cc:2350 +msgid "Reverse" +msgstr "ΑντιστÏοφή" + +#: gtk_ardour/editor.cc:2359 +#, fuzzy +msgid "Nudge fwd" +msgstr "νÏξη εμπÏός" + +#: gtk_ardour/editor.cc:2360 +#, fuzzy +msgid "Nudge bwd" +msgstr "ÎÏξη" + +#: gtk_ardour/editor.cc:2361 +msgid "Nudge fwd by capture offset" +msgstr "" + +#: gtk_ardour/editor.cc:2362 +msgid "Nudge bwd by capture offset" +msgstr "" + +#: gtk_ardour/editor.cc:2371 +msgid "Start to edit cursor" +msgstr "Από αÏχή μέχÏι κέÏσοÏα επεξεÏγασίας" + +#: gtk_ardour/editor.cc:2372 +msgid "Edit cursor to end" +msgstr "Από κέÏσοÏα επεξεÏγασίας μέχÏι τέλους" + +#: gtk_ardour/editor.cc:2374 +msgid "Trim" +msgstr "Ισοστάθμιση" + +#: gtk_ardour/editor.cc:2377 +msgid "Split" +msgstr "ΔιαχωÏισμός" + +#: gtk_ardour/editor.cc:2380 +msgid "Make mono regions" +msgstr "ΔημιουÏγία mono πεÏιοχών" + +#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428 +msgid "Duplicate" +msgstr "ΑντιγÏαφή" + +#: gtk_ardour/editor.cc:2384 +msgid "Fill Track" +msgstr "Γόμωση καναλιοÏ" + +#: gtk_ardour/editor.cc:2388 +msgid "Destroy" +msgstr "ΚαταστÏοφή" + +#: gtk_ardour/editor.cc:2418 +msgid "Play range" +msgstr "ΑναπαÏ/γή διαστήματος" + +#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446 +msgid "Loop range" +msgstr "Loop διαστήματος" + +#: gtk_ardour/editor.cc:2421 +msgid "Create chunk from range" +msgstr "ΔημιουÏγία ÎºÎ¿Î¼Î¼Î±Ï„Î¹Î¿Ï Î±Ï€ÏŒ διάστημα" + +#: gtk_ardour/editor.cc:2423 +msgid "Create Region" +msgstr "ΔημιουÏγία πεÏιοχής" + +#: gtk_ardour/editor.cc:2424 +msgid "Separate Region" +msgstr "ΔιαχωÏισμός πεÏιοχής" + +#: gtk_ardour/editor.cc:2425 +msgid "Crop Region to range" +msgstr "Κοπή ΠεÏιοχής στο διάστημα" + +#: gtk_ardour/editor.cc:2426 +msgid "Bounce range" +msgstr "Αναπήδηση διαστήματος" + +#: gtk_ardour/editor.cc:2432 +msgid "Fill range w/Region" +msgstr "Γέμισμα διαστήματος μ/ΠεÏιοχή" + +#: gtk_ardour/editor.cc:2434 +msgid "Range" +msgstr "Διάστημα" + +#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538 +msgid "Play from edit cursor" +msgstr "ΑναπαÏ/γή από ΚέÏσοÏα ΕπεξεÏγασίας" + +#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539 +msgid "Play from start" +msgstr "ΑναπαÏ/γή από αÏχή" + +#: gtk_ardour/editor.cc:2451 +#, fuzzy +msgid "Play region" +msgstr "ΑναπαÏ/γή ΠεÏιοχής" + +#: gtk_ardour/editor.cc:2453 +msgid "Loop Region" +msgstr "Loop ΠεÏιοχής" + +#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540 +#: gtk_ardour/library_ui.cc:972 +msgid "Play" +msgstr "ΑναπαÏ/γή" + +#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548 +msgid "Select All in track" +msgstr "Επιλογή όλων στο κανάλι" + +#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549 +msgid "Select All" +msgstr "Επιλογή όλων" + +#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550 +msgid "Invert in track" +msgstr "ΑντιστÏοφή στο κανάλι" + +#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551 +msgid "Invert" +msgstr "ΑντιστÏοφή" + +#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553 +msgid "Select loop range" +msgstr "Επιλογή διαστήματος loop" + +#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554 +msgid "Select punch range" +msgstr "Επιλογή διαστήματος punch" + +#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565 +#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369 +msgid "Cut" +msgstr "Κοπή" + +#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566 +#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371 +msgid "Copy" +msgstr "ΑντιγÏαφή" + +#: gtk_ardour/editor.cc:2482 +#, fuzzy +msgid "Paste at edit cursor" +msgstr "Από αÏχή μέχÏι κέÏσοÏα επεξεÏγασίας" + +#: gtk_ardour/editor.cc:2483 +#, fuzzy +msgid "Paste at mouse" +msgstr "χÏήση των master outs" + +#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923 +msgid "Align" +msgstr "ΕυθυγÏάμμιση" + +#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925 +msgid "Align Relative" +msgstr "ΕυθυγÏάμμιση σχετικών" + +#: gtk_ardour/editor.cc:2492 +msgid "Insert chunk" +msgstr "ΠÏοσθήκη κομματιοÏ" + +#: gtk_ardour/editor.cc:2496 +msgid "New Region from range" +msgstr "Îέα πεÏιοχή από διάστημα" + +#: gtk_ardour/editor.cc:2497 +msgid "Separate Range" +msgstr "ΞεχωÏιστό διάστημα" + +#: gtk_ardour/editor.cc:2507 +msgid "Insert Region" +msgstr "ΠÏοσθήκη πεÏιοχής" + +#: gtk_ardour/editor.cc:2508 +msgid "Insert external sndfile" +msgstr "ΠÏοσθήκη εξωτεÏÎ¹ÎºÎ¿Ï Î±Ïχείου ήχου" + +#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438 +msgid "Import" +msgstr "Εισαγωγή" + +#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574 +msgid "Nudge entire track fwd" +msgstr "ÎÏξη ολόκληÏου ÎºÎ±Î½Î±Î»Î¹Î¿Ï ÎµÎ¼Ï€Ïός" + +#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575 +msgid "Nudge track after edit cursor fwd" +msgstr "ÎÏξη ÎºÎ±Î½Î±Î»Î¹Î¿Ï Î¼ÎµÏ„Î¬ του κέÏσοÏα επεξεÏγασίας εμπÏός" + +#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576 +msgid "Nudge entire track bwd" +msgstr "ÎÏξη ολοκλήÏου ÎºÎ±Î½Î±Î»Î¹Î¿Ï Ï€Î¯ÏƒÏ‰" + +#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577 +msgid "Nudge track after edit cursor bwd" +msgstr "ÎÏξη κανάλι μετά του κέÏσοÏα επεξεÏγασίας πίσω" + +#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920 +#: gtk_ardour/redirect_box.cc:373 +msgid "Paste" +msgstr "Επικόλληση" + +#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645 +#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799 +msgid "add marker" +msgstr "Ï€Ïόσθεση στίγματος" + +#: gtk_ardour/editor.cc:3084 +msgid "select/move objects" +msgstr "επιλογή/μετακίνηση αντικειμένων" + +#: gtk_ardour/editor.cc:3085 +msgid "select/move ranges" +msgstr "επιλογή/μετακίνηση διαστημάτων" + +#: gtk_ardour/editor.cc:3086 +msgid "draw gain automation" +msgstr "σχεδιασμός Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Ï„Î¿Ï… gain" + +#: gtk_ardour/editor.cc:3087 +msgid "select zoom range" +msgstr "επιλογή διαστήματος zoom" + +#: gtk_ardour/editor.cc:3088 +msgid "stretch/shrink regions" +msgstr "μεγέθυνση/σμίκÏυνση πεÏιοχών" + +#: gtk_ardour/editor.cc:3089 +#, fuzzy +msgid "listen to specific regions" +msgstr "θέση επιλεγμένης οπτικής πεÏιοχής" + +#: gtk_ardour/editor.cc:3213 +msgid "Start:" +msgstr "ΑÏχή:" + +#: gtk_ardour/editor.cc:3214 +msgid "End:" +msgstr "Τέλος:" + +#: gtk_ardour/editor.cc:3215 +msgid "Edit:" +msgstr "ΣÏνταξη:" + +#: gtk_ardour/editor.cc:3429 +msgid "incorrectly formatted URI list, ignored" +msgstr "λανθασμένα φοÏμαÏισμένη URI λίστα, αγνοήθηκε" + +#: gtk_ardour/editor.cc:3611 +msgid "set selected trackview" +msgstr "θέση επιλεγμένης οπτικής καναλιοÏ" + +#: gtk_ardour/editor.cc:3647 +#, fuzzy +msgid "set selected control point" +msgstr "απαλοιφή σημείου ελέγχου" + +#: gtk_ardour/editor.cc:3719 +msgid "set selected regionview" +msgstr "θέση επιλεγμένης οπτικής πεÏιοχής" + +#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835 +#, fuzzy +msgid "set selected regions" +msgstr "θέση επιλεγμένης οπτικής πεÏιοχής" + +#: gtk_ardour/editor.cc:3891 +msgid "Undo" +msgstr "Undo" + +#: gtk_ardour/editor.cc:3893 +msgid "Undo (%1)" +msgstr "Undo (%1)" + +#: gtk_ardour/editor.cc:3903 +msgid "Redo" +msgstr "Redo" + +#: gtk_ardour/editor.cc:3905 +msgid "Redo (%1)" +msgstr "Redo (%1)" + +#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946 +msgid "... as new track" +msgstr "" + +#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947 +#, fuzzy +msgid "... as new region" +msgstr "ευθυγÏάμμιση πεÏιοχής" + +#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452 +msgid "Import audio (copy)" +msgstr "Εισαγωγή ήχου (αντίγÏαφο)" + +#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457 +msgid "Embed audio (link)" +msgstr "ΕμφÏτευση ήχου (link)" + +#: gtk_ardour/editor.cc:3953 +msgid "Remove last capture" +msgstr "Απαλοιφή τελευταίας λήψης" + +#: gtk_ardour/editor.cc:3974 +msgid "Duplicate how many times?" +msgstr "ΑντιγÏαφή πόσες φοÏές?" + +#: gtk_ardour/editor.cc:4550 +msgid "" +"Playlist %1 is currently unused.\n" +"If left alone, no audio files used by it will be cleaned.\n" +"If deleted, audio files used by it alone by will cleaned." +msgstr "" +"Η Λίστα ΑναπαÏ/γής %1 Ï€Ïος το παÏόν δε χÏησιμοποιείται.\n" +"Εάν μείνει έτσι, κανένα ηχητικό αÏχείο που χÏησιμοποιείται απο αυτήν δεν θα " +"διαγÏαφεί.\n" +"Εάν διαγÏαφεί, τα ηχητικά αÏχεία που χÏησιμοποιοÏνται μόνο απ'αυτήν θα " +"διαγÏαφοÏν." + +#: gtk_ardour/editor.cc:4555 +msgid "Delete playlist" +msgstr "ΔιαγÏαφή λίστας αναπαÏ/γής" + +#: gtk_ardour/editor.cc:4556 +msgid "Keep playlist" +msgstr "ΔιατήÏηση λίστας αναπαÏ/γής" + +#: gtk_ardour/editor.cc:4557 +msgid "Cancel cleanup" +msgstr "ΑκÏÏωση εκκαθάÏισης" + +#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258 +#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290 +msgid "" +"programming error: control point canvas item has no control point object " +"pointer!" +msgstr "" +"Σφάλμα ΠÏογÏαμματισμοÏ: ο καμβάς του σημείου ελέγχου δεν έχει δείκτη " +"αναφοÏάς!" + +#: gtk_ardour/editor_canvas_events.cc:717 +msgid "programming error: line canvas item has no line object pointer!" +msgstr "" +"Σφάλμα ΠÏογÏαμματισμοÏ: ο καμβάς της γÏαμμής δεν έχει δείκτη αναφοÏάς της " +"γÏαμμής!" + +#: gtk_ardour/editor_canvas_events.cc:744 +#: gtk_ardour/editor_canvas_events.cc:784 +#: gtk_ardour/editor_canvas_events.cc:823 +msgid "programming error: no \"rect\" pointer associated with selection item" +msgstr "" +"Σφάλμα Ï€ÏογÏαμματισμοÏ: κανένας \"rect\" δείκτης δεν σχετίζεται με το " +"επιλεγμένο αντικείμενο" + +#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298 +#: gtk_ardour/mixer_ui.cc:670 +msgid "Show All" +msgstr "Εμφάνιση Όλων" + +#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299 +#: gtk_ardour/mixer_ui.cc:671 +msgid "Hide All" +msgstr "ΑπόκÏυψη όλων" + +#: gtk_ardour/editor_edit_groups.cc:98 +msgid "Name for new edit group" +msgstr "Όνομα για νέα ομάδα επεξεÏγασίας" + +#: gtk_ardour/editor_export_audio.cc:60 +msgid "" +"There is no range to export.\n" +"\n" +"Select a range using the range mouse mode" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707 +msgid "programming error: no ImageFrameView selected" +msgstr "Σφάλμα Ï€ÏογÏαμματισμοÏ: δεν επιλέχθηκε οπτική καÏέ εικόνας" + +#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930 +msgid "programming error: no MarkerView selected" +msgstr "Σφάλμα Ï€ÏογÏαμματισμοÏ: δεν επιλέχθηκε οπτική στίγματος" + +#: gtk_ardour/editor_keys.cc:187 +#, fuzzy +msgid "keyboard selection" +msgstr "επέκταση επιλογής" + +#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376 +#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526 +#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584 +#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650 +#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700 +#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960 +#: gtk_ardour/editor_mouse.cc:4075 +msgid "programming error: marker canvas item has no marker object pointer!" +msgstr "" +"Σφάλμα Ï€ÏογÏαμματισμοÏ: ο καμβάς στιγμάτων δεν έχει δείκτη αντικειμένου " +"στιγμάτων!" + +#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681 +msgid "remove marker" +msgstr "απαλοιφή στίγματος" + +#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494 +msgid "Locate to" +msgstr "Τοποθέτηση στο" + +#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495 +msgid "Play from" +msgstr "ΑναπαÏ/γή από" + +#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496 +msgid "Set from playhead" +msgstr "Θέση από αναπαÏαγωγέα" + +#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497 +msgid "Set from range" +msgstr "Θέση από διάστημα" + +#: gtk_ardour/editor_markers.cc:479 +msgid "Set Loop Range" +msgstr "Θέση Loop Διαστήματος" + +#: gtk_ardour/editor_markers.cc:480 +msgid "Set Punch Range" +msgstr "Θέση Punch Διαστήματος" + +#: gtk_ardour/editor_markers.cc:736 +msgid "ardour: rename mark" +msgstr "ardour: μετονομασία στίγματος" + +#: gtk_ardour/editor_markers.cc:738 +#, fuzzy +msgid "ardour: rename range" +msgstr "ardour: μετονομασία πεÏιοχής" + +#: gtk_ardour/editor_markers.cc:792 +msgid "set loop range" +msgstr "Θέση loop διαστήματος" + +#: gtk_ardour/editor_markers.cc:818 +msgid "set punch range" +msgstr "θέση punch διαστήματος" + +#: gtk_ardour/editor_mouse.cc:99 +msgid "Editor::event_frame() used on unhandled event type %1" +msgstr "" +"ΕπαξεÏγαστής::event_frame() χÏησιμοποιήθηκε στο αδιαχείÏιστο συμβάν Ï„Ïπου %1" + +#: gtk_ardour/editor_mouse.cc:1555 +msgid "programming error: start_grab called without drag item" +msgstr "" +"σφάλμα Ï€ÏογÏαμματισμοÏ: η Ïουτίνα start_grab εκλήθη δίχως 'drag' αντικείμενο" + +#: gtk_ardour/editor_mouse.cc:1760 +msgid "change fade in length" +msgstr "αλλαγή μήκους fade in" + +#: gtk_ardour/editor_mouse.cc:1778 +msgid "programming error: fade out canvas item has no regionview data pointer!" +msgstr "" +"σφάλμα Ï€ÏογÏαμματισμοÏ: ο καμβάς fade out δεν έχει δείκτη δεδομένων της " +"οπτικής πεÏιοχών!" + +#: gtk_ardour/editor_mouse.cc:1852 +msgid "change fade out length" +msgstr "αλλαγή μήκους fade out" + +#: gtk_ardour/editor_mouse.cc:1871 +msgid "programming error: cursor canvas item has no cursor data pointer!" +msgstr "" +"σφάλμα Ï€ÏογÏαμματισμοÏ: ο καμβάς του κέÏσοÏα δεν έχει δείκτη δεδομένων του " +"κέÏσοÏα!" + +#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470 +msgid "" +"programming error: meter marker canvas item has no marker object pointer!" +msgstr "" +"σφάλμα Ï€ÏογÏαμματισμοÏ: ο καμβάς του μετÏητή στιγμάτων δεν έχει δείκτη " +"αντικειμένου στιγμάτων!" + +#: gtk_ardour/editor_mouse.cc:2163 +msgid "move meter mark" +msgstr "μετακίνηση στίγματος μετÏητή" + +#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335 +#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439 +msgid "" +"programming error: tempo marker canvas item has no marker object pointer!" +msgstr "" +"σφάλμα Ï€ÏογÏαμματισμοÏ: ο καμβάς στίξης του tempo δεν έχει δείκτη " +"αντικειμένου στιγμάτων!" + +#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340 +#: gtk_ardour/editor_tempodisplay.cc:425 +msgid "programming error: marker for tempo is not a tempo marker!" +msgstr "" +"σφάλμα Ï€ÏογÏαμματισμοÏ: το στίγμα για το tempo δεν είναι στιγμα για tempo!" + +#: gtk_ardour/editor_mouse.cc:2245 +msgid "move tempo mark" +msgstr "μετακίνηση στίγματος tempo" + +#: gtk_ardour/editor_mouse.cc:2388 +msgid "programming error: line canvas item has no line pointer!" +msgstr "σφάλμα Ï€ÏογÏαμματισμοÏ: ο καμβάς γÏαμμών δεν έχει δείκτη γÏαμμών!" + +#: gtk_ardour/editor_mouse.cc:2497 +#, fuzzy +msgid "move region(s)" +msgstr "απαλοιφή πεÏιοχής" + +#: gtk_ardour/editor_mouse.cc:2509 +msgid "Drag region copy" +msgstr "Έλξη αντιγÏαφής πεÏιοχής" + +#: gtk_ardour/editor_mouse.cc:2579 +#, fuzzy +msgid "copy region(s)" +msgstr "Έλξη πεÏιοχής(ων)" + +#: gtk_ardour/editor_mouse.cc:2612 +#, fuzzy +msgid "Drag region brush" +msgstr "Έλξη πεÏιοχής(ων)" + +#: gtk_ardour/editor_mouse.cc:3425 +msgid "selection grab" +msgstr "αÏπαγή επιλεγμένων" + +#: gtk_ardour/editor_mouse.cc:3571 +msgid "range selection" +msgstr "επιλογή διαστήματος" + +#: gtk_ardour/editor_mouse.cc:3587 +msgid "trim selection start" +msgstr "αÏχή επιλογής Ï€Ïος ισοστάθμιση" + +#: gtk_ardour/editor_mouse.cc:3603 +msgid "trim selection end" +msgstr "τέλος επιλογής Ï€Ïος ισοστάθμιση" + +#: gtk_ardour/editor_mouse.cc:3620 +msgid "move selection" +msgstr "μετακίνηση επιλογής" + +#: gtk_ardour/editor_mouse.cc:3995 +msgid "Start point trim" +msgstr "ΑÏχή σημείου ισοσταθμίσεως" + +#: gtk_ardour/editor_mouse.cc:4023 +msgid "End point trim" +msgstr "Τέλος σημείου ισοσταθμίσεως" + +#: gtk_ardour/editor_mouse.cc:4062 +msgid "trimmed region" +msgstr "ισοσταθμισμένη πεÏιοχή" + +#: gtk_ardour/editor_mouse.cc:4203 +msgid "new range marker" +msgstr "νέο στίγμα διαστήματος" + +#: gtk_ardour/editor_mouse.cc:4422 +msgid "select regions" +msgstr "επιλογή πεÏιοχών" + +#: gtk_ardour/editor_mouse.cc:4451 +msgid "Name for region:" +msgstr "Όνομα για πεÏιοχή:" + +#: gtk_ardour/editor_mouse.cc:4517 +msgid "timestretch" +msgstr "κάμψη χÏόνου" + +#: gtk_ardour/editor_ops.cc:117 +msgid "split" +msgstr "διαχωÏισμός" + +#: gtk_ardour/editor_ops.cc:153 +msgid "remove region" +msgstr "απαλοιφή πεÏιοχής" + +#: gtk_ardour/editor_ops.cc:172 +msgid "" +" This is destructive, will possibly delete audio files\n" +"It cannot be undone\n" +"Do you really want to destroy %1 ?" +msgstr "" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "these regions" +msgstr "αντιστÏοφή πεÏιοχών" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "this region" +msgstr "σιγή παÏοÏσας πεÏιοχής" + +#: gtk_ardour/editor_ops.cc:179 +#, fuzzy +msgid "Yes, destroy them." +msgstr "Îαι, να καταστÏαφεί." + +#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434 +msgid "Yes, destroy it." +msgstr "Îαι, να καταστÏαφεί." + +#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435 +#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300 +msgid "No, do nothing." +msgstr "Όχι, να μην γίνει τίποτα." + +#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307 +msgid "extend selection" +msgstr "επέκταση επιλογής" + +#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357 +#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427 +msgid "nudge forward" +msgstr "νÏξη εμπÏός" + +#: gtk_ardour/editor_ops.cc:491 +msgid "build_region_boundary_cache called with snap_type = %1" +msgstr "build_region_boundary_cache εκλήθη με snap_type = %1" + +#: gtk_ardour/editor_ops.cc:1305 +msgid "set selection from range" +msgstr "θέση επιλογής από διάστημα" + +#: gtk_ardour/editor_ops.cc:1421 +msgid "clear markers" +msgstr "εκκαθάÏιση στιγμάτων" + +#: gtk_ardour/editor_ops.cc:1433 +msgid "clear ranges" +msgstr "διαγÏαφή διαστημάτων" + +#: gtk_ardour/editor_ops.cc:1452 +msgid "clear locations" +msgstr "διαγÏαφή τοποθεσιών" + +#: gtk_ardour/editor_ops.cc:1503 +msgid "insert dragged region" +msgstr "Ï€Ïοσθήκη ελκομένης πεÏιοχής" + +#: gtk_ardour/editor_ops.cc:1538 +msgid "insert region" +msgstr "Ï€Ïοσθήκη πεÏιοχής" + +#: gtk_ardour/editor_ops.cc:1744 +msgid "ardour: rename region" +msgstr "ardour: μετονομασία πεÏιοχής" + +#: gtk_ardour/editor_ops.cc:1891 +msgid "You can't import an audiofile until you have a session loaded." +msgstr "Δεν γίνεται να εισαχθεί ήχος χωÏίς να έχει φοÏτωθεί Ï€Ïώτα ΣυνεδÏία." + +#: gtk_ardour/editor_ops.cc:1901 +#, fuzzy +msgid "Import selected as tracks" +msgstr "Εισαγωγή επιλεγμένου(ων)" + +#: gtk_ardour/editor_ops.cc:1904 +#, fuzzy +msgid "Import selected to region list" +msgstr "θέση επιλεγμένης οπτικής πεÏιοχής" + +#: gtk_ardour/editor_ops.cc:1933 +msgid "ardour: audio import in progress" +msgstr "ardour: εισαγωγή ήχων εν εξελίξι" + +#: gtk_ardour/editor_ops.cc:1937 +msgid "Cancel Import" +msgstr "ΑκÏÏωση Εισαγωγής" + +#: gtk_ardour/editor_ops.cc:1944 +msgid "ardour: importing %1" +msgstr "ardour: εισαγωγή εν εξελίξι %1" + +#: gtk_ardour/editor_ops.cc:1990 +msgid "%1 it anyway" +msgstr "%1 το οÏτως ή άλλως" + +#: gtk_ardour/editor_ops.cc:1996 +#, fuzzy +msgid "Don't %1 it" +msgstr "Μη %1" + +#: gtk_ardour/editor_ops.cc:1997 +msgid "%1 all without questions" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1998 +#, fuzzy +msgid "Cancel entire import" +msgstr "ΑκÏÏωση Εισαγωγής" + +#: gtk_ardour/editor_ops.cc:2004 +msgid "" +"%1\n" +"This audiofile's sample rate doesn't match the session sample rate!" +msgstr "" +"%1\n" +"Ο Ïυθμός δειγματοληψίας Î±Ï…Ï„Î¿Ï Ï„Î¿Ï… αÏχείου δεν ταιÏιάζει με αυτόν της " +"συνεδÏίας!" + +#: gtk_ardour/editor_ops.cc:2032 +msgid "You can't embed an audiofile until you have a session loaded." +msgstr "" +"Δεν γίνεται να εμφυτεÏσετε ηχο-αÏχεία μέχÏι να φοÏτώσετε κάποια συνεδÏία." + +#: gtk_ardour/editor_ops.cc:2039 +msgid "Add to External Region list" +msgstr "ΠÏόσθεση σε Λίστα ΕξωτεÏικής ΠεÏιοχής" + +#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210 +#: gtk_ardour/editor_ops.cc:2286 +msgid "Editor: cannot open file \"%1\" (%2)" +msgstr "Editor: δεν γίνεται να ανοίξει το αÏχείο \"%1\" (%2)" + +#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312 +msgid "could not open %1" +msgstr "δεν μπόÏεσα να ανοίξω το %1" + +#: gtk_ardour/editor_ops.cc:2171 +#, fuzzy +msgid "Insert selected as new tracks" +msgstr "θέση επιλεγμένης οπτικής καναλιοÏ" + +#: gtk_ardour/editor_ops.cc:2186 +msgid "Insert selected" +msgstr "ΠÏοσθήκη επιλεγμένου(ων)" + +#: gtk_ardour/editor_ops.cc:2327 +msgid "insert sndfile" +msgstr "Ï€Ïοσθήκη ηχο-αÏχείου" + +#: gtk_ardour/editor_ops.cc:2464 +msgid "separate" +msgstr "διαχωÏισμός" + +#: gtk_ardour/editor_ops.cc:2528 +msgid "trim to selection" +msgstr "ισοστάθμιση Ï€Ïος τα επιλεγμένα" + +#: gtk_ardour/editor_ops.cc:2568 +msgid "region fill" +msgstr "γόμωση πεÏιοχής" + +#: gtk_ardour/editor_ops.cc:2626 +msgid "fill selection" +msgstr "γόμωση επιλογής" + +#: gtk_ardour/editor_ops.cc:2650 +msgid "Place the edit cursor at the desired sync point" +msgstr "Τοποθετήστε τον κεÏσοÏα επεξεÏ/σίας στο επιθÏμητό σημείο συγχÏονισμοÏ" + +#: gtk_ardour/editor_ops.cc:2656 +msgid "set sync from edit cursor" +msgstr "Θέση συγχÏονισμοÏ(sync) απο κέÏσοÏα επεξεÏ/σίας" + +#: gtk_ardour/editor_ops.cc:2668 +msgid "remove sync" +msgstr "απαλοιφή συγχÏονισμοÏ(sync)" + +#: gtk_ardour/editor_ops.cc:2682 +msgid "naturalize" +msgstr "φυσικοποίηση" + +#: gtk_ardour/editor_ops.cc:2746 +msgid "align selection (relative)" +msgstr "ευθυγÏάμμιση επιλογής (σχετική)" + +#: gtk_ardour/editor_ops.cc:2774 +msgid "align selection" +msgstr "ευθυγÏάμμιση επιλογής" + +#: gtk_ardour/editor_ops.cc:2786 +msgid "align region" +msgstr "ευθυγÏάμμιση πεÏιοχής" + +#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858 +msgid "trim to edit" +msgstr "ισοστάθμιση Ï€Ïος σÏνταξη" + +#: gtk_ardour/editor_ops.cc:2909 +#, fuzzy +msgid "ardour: freeze" +msgstr "ardour: " + +#: gtk_ardour/editor_ops.cc:2914 +#, fuzzy +msgid "Cancel Freeze" +msgstr "ΑκÏÏωση" + +#: gtk_ardour/editor_ops.cc:2951 +msgid "bounce range" +msgstr "αναπήδηση διαστήματο" + +#: gtk_ardour/editor_ops.cc:3004 +msgid "cut" +msgstr "κοπή" + +#: gtk_ardour/editor_ops.cc:3007 +msgid "copy" +msgstr "αντιγÏαφή" + +#: gtk_ardour/editor_ops.cc:3020 +msgid " objects" +msgstr " αντικειμένων" + +#: gtk_ardour/editor_ops.cc:3046 +msgid " range" +msgstr " διαστήματος" + +#: gtk_ardour/editor_ops.cc:3201 +msgid "paste" +msgstr "επικόλληση" + +#: gtk_ardour/editor_ops.cc:3236 +msgid "paste chunk" +msgstr "επικόλληση κομματιοÏ" + +#: gtk_ardour/editor_ops.cc:3276 +msgid "duplicate region" +msgstr "αντιγÏαφή πεÏιοχής" + +#: gtk_ardour/editor_ops.cc:3309 +msgid "duplicate selection" +msgstr "αντιγÏαφή επιλογής" + +#: gtk_ardour/editor_ops.cc:3349 +msgid "clear playlist" +msgstr "εκκαθάÏιση playlist" + +#: gtk_ardour/editor_ops.cc:3378 +msgid "nudge track" +msgstr "νÏξη καναλιοÏ" + +#: gtk_ardour/editor_ops.cc:3431 +msgid "" +"Do you really want to destroy the last capture?\n" +"(This is destructive and cannot be undone)" +msgstr "" +"Στ'αλήθεια θέλετε να καταστÏέψετε την τελευταία λήψη?\n" +"(Η Ï€Ïάξη είνα‎ι καταστÏεπτική και δεν γίνεται επαναφοÏά της)" + +#: gtk_ardour/editor_ops.cc:3463 +msgid "normalize" +msgstr "εξομάλυνση" + +#: gtk_ardour/editor_ops.cc:3510 +msgid "reverse regions" +msgstr "αντιστÏοφή πεÏιοχών" + +#: gtk_ardour/editor_region_list.cc:223 +#, fuzzy +msgid "hidden" +msgstr "ΚÏυμμένο" + +#: gtk_ardour/editor_region_list.cc:408 +msgid "Show all" +msgstr "Ανάδειξη όλων" + +#: gtk_ardour/editor_region_list.cc:417 +msgid "Ascending" +msgstr "ΑÏξουσα" + +#: gtk_ardour/editor_region_list.cc:419 +msgid "Descending" +msgstr "Φθίνουσα" + +#: gtk_ardour/editor_region_list.cc:423 +msgid "By Region Name" +msgstr "Με Όνομα ΠεÏιοχής" + +#: gtk_ardour/editor_region_list.cc:425 +msgid "By Region Length" +msgstr "Με Μέγεθος ΠεÏιοχής" + +#: gtk_ardour/editor_region_list.cc:427 +msgid "By Region Position" +msgstr "Με Θέση ΠεÏιοχής" + +#: gtk_ardour/editor_region_list.cc:429 +msgid "By Region Timestamp" +msgstr "Με ΧÏονο-στάμπα ΠεÏιοχής" + +#: gtk_ardour/editor_region_list.cc:431 +msgid "By Region Start in File" +msgstr "Με ΑÏχή-στο-αÏχείο της ΠεÏιοχής" + +#: gtk_ardour/editor_region_list.cc:433 +msgid "By Region End in File" +msgstr "Με Τέλος-στο -αÏχείο της ΠεÏιοχής" + +#: gtk_ardour/editor_region_list.cc:435 +msgid "By Source File Name" +msgstr "Με Όνομα ΑÏχείου Πηγής" + +#: gtk_ardour/editor_region_list.cc:437 +msgid "By Source File Length" +msgstr "Με Μέγεθος ΑÏχείου Πηγής" + +#: gtk_ardour/editor_region_list.cc:439 +msgid "By Source File Creation Date" +msgstr "Με Ημ/νία ΑÏχείου Πηγής" + +#: gtk_ardour/editor_region_list.cc:441 +msgid "By Source Filesystem" +msgstr "Με Filesystem Πηγής" + +#: gtk_ardour/editor_region_list.cc:444 +msgid "Sorting" +msgstr "Ταξινόμηση" + +#: gtk_ardour/editor_region_list.cc:808 +msgid "Regions/length" +msgstr "ΠεÏιοχές/διάÏκεια" + +#: gtk_ardour/editor_region_list.cc:812 +msgid "Regions/position" +msgstr "ΠεÏιοχές/θέση" + +#: gtk_ardour/editor_region_list.cc:816 +msgid "Regions/creation" +msgstr "ΠεÏιοχές/δημιουÏγία" + +#: gtk_ardour/editor_region_list.cc:820 +msgid "Regions/start" +msgstr "ΠεÏιοχές/αÏχή" + +#: gtk_ardour/editor_region_list.cc:824 +msgid "Regions/end" +msgstr "ΠεÏιοχές/τέλος" + +#: gtk_ardour/editor_region_list.cc:828 +msgid "Regions/file name" +msgstr "ΠεÏιοχές/όνομα αÏχείου" + +#: gtk_ardour/editor_region_list.cc:832 +msgid "Regions/file size" +msgstr "ΠεÏιοχές/μέγεθος αÏχείου" + +#: gtk_ardour/editor_region_list.cc:836 +msgid "Regions/file date" +msgstr "ΠεÏιοχές/ημ/νία αÏχείου" + +#: gtk_ardour/editor_region_list.cc:840 +msgid "Regions/file system" +msgstr "ΠεÏιοχές/file system" + +#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73 +#: gtk_ardour/editor_route_list.cc:231 +msgid "editor" +msgstr "επεξεÏγαστής" + +#: gtk_ardour/editor_route_list.cc:300 +msgid "Show All AbstractTracks" +msgstr "Ανάδειξη όλων των Abstractκανάλιs" + +#: gtk_ardour/editor_route_list.cc:301 +msgid "Hide All AbstractTracks" +msgstr "ΑπόκÏυψη όλων των Abstractκαναλιών" + +#: gtk_ardour/editor_route_list.cc:302 +msgid "Show All AudioBus" +msgstr "Ανάδειξη όλων των ΗχοδιαÏλων" + +#: gtk_ardour/editor_route_list.cc:303 +msgid "Hide All AudioBus" +msgstr "ΑπόκÏυψη όλων των ΗχοδιαÏλων" + +#: gtk_ardour/editor_rulers.cc:311 +msgid "New location marker" +msgstr "Îέο στίγμα θέσεως" + +#: gtk_ardour/editor_rulers.cc:312 +msgid "Clear all locations" +msgstr "ΕκκαθάÏιση όλων των θέσεων" + +#: gtk_ardour/editor_rulers.cc:317 +msgid "Clear all ranges" +msgstr "ΕκκαθάÏιση όλων των διαστημάτων" + +#: gtk_ardour/editor_rulers.cc:326 +msgid "New Tempo" +msgstr "Îέος ΧÏόνος" + +#: gtk_ardour/editor_rulers.cc:327 +msgid "Clear tempo" +msgstr "ΕκκαθάÏιση ΧÏόνου" + +#: gtk_ardour/editor_rulers.cc:332 +msgid "New Meter" +msgstr "Îέο μέτÏο" + +#: gtk_ardour/editor_rulers.cc:333 +msgid "Clear meter" +msgstr "ΕκκαθάÏιση μέτÏου" + +#: gtk_ardour/editor_rulers.cc:341 +msgid "Min:Secs" +msgstr "Λεπ:ΔεÏÏ„" + +#: gtk_ardour/editor_selection_list.cc:117 +msgid "name for chunk:" +msgstr "όνομα για κομμάτι:" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Create chunk" +msgstr "ΔημιουÏγία κομματιοÏ" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Forget it" +msgstr "Ξέχασέ το" + +#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295 +msgid "add" +msgstr "Ï€Ïόσθεση" + +#: gtk_ardour/editor_tempodisplay.cc:276 +msgid "add tempo mark" +msgstr "Ï€Ïόσθεση στίγματος χÏόνου" + +#: gtk_ardour/editor_tempodisplay.cc:318 +msgid "add meter mark" +msgstr "Ï€Ïόσθεση στίγματος μέτÏου" + +#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383 +msgid "done" +msgstr "έγινε" + +#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404 +msgid "replace tempo mark" +msgstr "αντικατάσταση στίγματος χÏόνου" + +#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475 +msgid "programming error: marker for meter is not a meter marker!" +msgstr "" +"Σφάλμα Ï€ÏογÏαμματισμοÏ: το στίγμα για το μέτÏο δεν είναι στίγμα μέτÏου!" + +#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487 +msgid "remove tempo mark" +msgstr "απαλοιφή στίγματος χÏόνου" + +#: gtk_ardour/editor_timefx.cc:50 +msgid "Quick but Ugly" +msgstr "ΓÏήγοÏο αλλά Άσχημο" + +#: gtk_ardour/editor_timefx.cc:51 +msgid "Skip Anti-aliasing" +msgstr "ΠαÏάκαμψη Anti-aliasing" + +#: gtk_ardour/editor_timefx.cc:53 +msgid "Stretch/Shrink it" +msgstr "Μεγέθυνέ/ΣμίκÏυνέ το" + +#: gtk_ardour/editor_timefx.cc:57 +msgid "ardour: timestretch" +msgstr "ardour: χÏονοκάμψη" + +#: gtk_ardour/editor_timefx.cc:58 +msgid "TimeStretchDialog" +msgstr "ΔιάλογοςΧÏονοκάμψης" + +#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83 +#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85 +msgid "TimeStretchButton" +msgstr "ΚουμπίΧÏονοκάμψης" + +#: gtk_ardour/editor_timefx.cc:86 +msgid "TimeStretchProgress" +msgstr "ΠÏόοδοςΧÏονοκάμψης" + +#: gtk_ardour/editor_timefx.cc:151 +msgid "timestretch cannot be started - thread creation error" +msgstr "" + +#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410 +#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189 +msgid "22.05kHz" +msgstr "22.05kHz" + +#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413 +#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949 +#: gtk_ardour/export_dialog.cc:1191 +msgid "44.1kHz" +msgstr "44.1kHz" + +#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416 +#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193 +msgid "48kHz" +msgstr "48kHz" + +#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419 +#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195 +msgid "88.2kHz" +msgstr "88.2kHz" + +#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422 +#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197 +msgid "96kHz" +msgstr "96kHz" + +#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425 +#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199 +msgid "192kHz" +msgstr "192kHz" + +#: gtk_ardour/export_dialog.cc:73 +msgid "best" +msgstr "βέλτιστη" + +#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964 +msgid "fastest" +msgstr "ταχÏτατη" + +#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966 +msgid "linear" +msgstr "γÏαμμική" + +#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968 +msgid "better" +msgstr "καλÏτεÏη" + +#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970 +msgid "intermediate" +msgstr "ενδιάμεση" + +#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979 +msgid "Rectangular" +msgstr "ΤετÏάγωνη" + +#: gtk_ardour/export_dialog.cc:84 +msgid "Shaped Noise" +msgstr "ΜοÏφοποιημένος ΘόÏυβος" + +#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981 +msgid "Triangular" +msgstr "ΤÏίγωνη" + +#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336 +msgid "stereo" +msgstr "stereo" + +#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497 +#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219 +#: gtk_ardour/utils.cc:334 +msgid "mono" +msgstr "mono" + +#: gtk_ardour/export_dialog.cc:97 +msgid "CUE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:98 +msgid "TOC" +msgstr "" + +#: gtk_ardour/export_dialog.cc:106 +msgid "FORMAT" +msgstr "FORMAT" + +#: gtk_ardour/export_dialog.cc:107 +msgid "SAMPLE RATE" +msgstr "ΡΥΘΜΟΣ ΔΕΙΓΜΑΤ/ΨΙΑΣ" + +#: gtk_ardour/export_dialog.cc:108 +msgid "CONVERSION QUALITY" +msgstr "ΠΟΙΟΤΗΤΑ ΜΕΤΑΤΡΟΠΗΣ" + +#: gtk_ardour/export_dialog.cc:109 +msgid "DITHER TYPE" +msgstr "ΤΥΠΟΣ DITHER" + +#: gtk_ardour/export_dialog.cc:110 +#, fuzzy +msgid "CD MARKER FILE TYPE" +msgstr "ΤΥΠΟΣ ΑΡΧΕΙΟΥ" + +#: gtk_ardour/export_dialog.cc:111 +msgid "CHANNELS" +msgstr "ΚΑÎΑΛΙΑ" + +#: gtk_ardour/export_dialog.cc:112 +msgid "FILE TYPE" +msgstr "ΤΥΠΟΣ ΑΡΧΕΙΟΥ" + +#: gtk_ardour/export_dialog.cc:113 +msgid "SAMPLE FORMAT" +msgstr "FORMAT ΔΕΙΓΜΑΤΟΣ" + +#: gtk_ardour/export_dialog.cc:114 +msgid "SAMPLE ENDIANNESS" +msgstr "SAMPLE ENDIANNESS" + +#: gtk_ardour/export_dialog.cc:115 +#, fuzzy +msgid "EXPORT CD MARKER FILE ONLY" +msgstr "ΤΥΠΟΣ ΑΡΧΕΙΟΥ" + +#: gtk_ardour/export_dialog.cc:116 +msgid "EXPORT TO FILE" +msgstr "ΕΞΑΓΩΓΗ ΣΕ ΑΡΧΕΙΟ" + +#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118 +#: gtk_ardour/option_editor.cc:119 +msgid "Browse" +msgstr "Αναζήτηση" + +#: gtk_ardour/export_dialog.cc:119 +msgid "Specific tracks ..." +msgstr "" + +#: gtk_ardour/export_dialog.cc:131 +msgid "ardour: export" +msgstr "ardour: εξαγωγή" + +#: gtk_ardour/export_dialog.cc:132 +msgid "ardour_export" +msgstr "ardour_εξαγωγή" + +#: gtk_ardour/export_dialog.cc:156 +#, fuzzy +msgid "Output" +msgstr "Έξοδοι" + +#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626 +msgid "Track" +msgstr "Κανάλι" + +#: gtk_ardour/export_dialog.cc:287 +msgid "slereg" +msgstr "slereg" + +#: gtk_ardour/export_dialog.cc:658 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD toc file" +msgstr "" +"ΕπεξεÏγαστής: δεν γίνεται να ανοιχτεί το \"%1\" ως αÏχείο εξαγωγής για " +"στίγματα ÎºÎ±Î½Î±Î»Î¹Î¿Ï CD" + +#: gtk_ardour/export_dialog.cc:780 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD cue file" +msgstr "" +"ΕπεξεÏγαστής: δεν γίνεται να ανοιχτεί το \"%1\" ως αÏχείο εξαγωγής για " +"στίγματα ÎºÎ±Î½Î±Î»Î¹Î¿Ï CD" + +#: gtk_ardour/export_dialog.cc:799 +msgid "WAV" +msgstr "" + +#: gtk_ardour/export_dialog.cc:1051 +msgid "Stop Export" +msgstr "ΠαÏση Εξαγωγής" + +#: gtk_ardour/gain_automation_time_axis.cc:60 +#, fuzzy +msgid "add gain automation event" +msgstr "Ï€Ïόσθεση συμβάντος Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï ÏƒÎµ " + +#: gtk_ardour/gain_meter.cc:68 +msgid "Cannot create slider pixmaps" +msgstr "" + +#: gtk_ardour/gain_meter.cc:83 +msgid "dbFS" +msgstr "dbFS" + +#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134 +#: gtk_ardour/gain_meter.cc:728 +msgid "pre" +msgstr "Ï€Ïο" + +#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724 +#, fuzzy +msgid "input" +msgstr "%1 είσοδος" + +#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732 +#, fuzzy +msgid "post" +msgstr "θÏÏα" + +#: gtk_ardour/gain_meter.cc:146 +msgid "tupni" +msgstr "" + +#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470 +#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537 +msgid "-inf" +msgstr "-inf" + +#: gtk_ardour/imageframe_socket_handler.cc:127 +msgid "Image Compositor Socket has been shutdown/closed" +msgstr "Η Socket για τον Image Compositor έχει τεÏματιστεί/κλείσει" + +#: gtk_ardour/imageframe_time_axis.cc:295 +#, fuzzy +msgid "0.5 seconds" +msgstr "ΔευτεÏόλεπτα" + +#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259 +#, fuzzy +msgid "1 seconds" +msgstr "ΔευτεÏόλεπτα" + +#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260 +#, fuzzy +msgid "1.5 seconds" +msgstr "ΔευτεÏόλεπτα" + +#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261 +#, fuzzy +msgid "2 seconds" +msgstr "ΔευτεÏόλεπτα" + +#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262 +#, fuzzy +msgid "2.5 seconds" +msgstr "ΔευτεÏόλεπτα" + +#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263 +#, fuzzy +msgid "3 seconds" +msgstr "ΔευτεÏόλεπτα" + +#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268 +#, fuzzy +msgid "Duration (sec)" +msgstr "Έλξη πεÏιοχής(ων)" + +#: gtk_ardour/imageframe_time_axis.cc:310 +#, fuzzy +msgid "Remove Frame" +msgstr "Απαλοιφή Πεδίου" + +#: gtk_ardour/imageframe_time_axis.cc:313 +#, fuzzy +msgid "Image Frame" +msgstr "Frames" + +#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274 +#, fuzzy +msgid "Rename Track" +msgstr "Μετονομασία" + +#: gtk_ardour/io_selector.cc:64 +msgid "%1 input" +msgstr "%1 είσοδος" + +#: gtk_ardour/io_selector.cc:66 +msgid "%1 output" +msgstr "%1 έξοδος" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103 +msgid "Inputs" +msgstr "Είσοδοι" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104 +msgid "Outputs" +msgstr "Έξοδοι" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Input" +msgstr "Ï€Ïόσθεση εισόδου" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Output" +msgstr "Ï€Ïόσθεση εξόδου" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Input" +msgstr "Απαλοιφή σημείου συγχÏονισμοÏ" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Output" +msgstr "# Έξοδοι" + +#: gtk_ardour/io_selector.cc:144 +#, fuzzy +msgid "Disconnect All" +msgstr "ΑποσÏνδεση" + +#: gtk_ardour/io_selector.cc:158 +msgid "Available connections" +msgstr "Διαθέσιμες Συνδέσεις" + +#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636 +#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724 +msgid "port" +msgstr "θÏÏα" + +#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587 +msgid "There are no more JACK ports available." +msgstr "" + +#: gtk_ardour/io_selector.cc:790 +msgid "ardour: " +msgstr "ardour: " + +#: gtk_ardour/keyboard.cc:419 +msgid "KeyboardTarget: keyname \"%1\" is unknown." +msgstr "KeyboardTarget: το Όνομα ΠλήκτÏου \"%1\" είναι άγνωστο." + +#: gtk_ardour/keyboard.cc:645 +msgid "" +"Your system is completely broken - NumLock uses \"%1\"as its modifier. This " +"is madness - see the man page for xmodmap to find out how to fix this." +msgstr "" +"Το ΣÏστημά σας έχει χαλάσει τελείως - Το NumLock χÏησιμοποιεί το \"%1\"σαν " +"μεταβλητή του. Αυτό είναι Ï„Ïέλα - ανατÏέξτε στην man page του xmodmap για να " +"βÏείτε πώς θα το φτιάξετε." + +#: gtk_ardour/keyboard.cc:653 +msgid "" +"Your system generates \"%1\" when the NumLock key is pressed. This can cause " +"problems when editing so Ardour will use %2 to mean Meta rather than %1" +msgstr "" +"Το ΣÏστημά σας δημιουÏγεί \"%1\" όταν το NumLock είναι εν ενεÏγεία. Αυτό " +"μποÏεί να δημιουÏγήσει Ï€Ïοβλήματα στην επεξεÏγασία οπότε ο Ardour θα " +"χÏησιμοποιήσει %2 για Meta αντί του %1" + +#: gtk_ardour/keyboard.cc:714 +msgid "You have %1 keys bound to \"mod1\"" +msgstr "ΥπάÏχουν %1 πλήκτÏα αναθεμένα στο \"mod1\"" + +#: gtk_ardour/keyboard.cc:729 +msgid "You have %1 keys bound to \"mod2\"" +msgstr "ΥπάÏχουν %1 πλήκτÏα αναθεμένα στο \"mod2\"" + +#: gtk_ardour/keyboard.cc:744 +msgid "You have %1 keys bound to \"mod3\"" +msgstr "ΥπάÏχουν %1 πλήκτÏα αναθεμένα στο \"mod3\"" + +#: gtk_ardour/keyboard.cc:759 +msgid "You have %1 keys bound to \"mod4\"" +msgstr "ΥπάÏχουν %1 πλήκτÏα αναθεμένα στο \"mod4\"" + +#: gtk_ardour/keyboard.cc:774 +msgid "You have %1 keys bound to \"mod5\"" +msgstr "ΥπάÏχουν %1 πλήκτÏα αναθεμένα στο \"mod5\"" + +#: gtk_ardour/keyboard_target.cc:72 +msgid "KeyboardTarget: empty string passed to add_binding." +msgstr "KeyboardTarget: κενή γÏαμμή στην Ï€Ïόσθεση_δεσμοÏ." + +#: gtk_ardour/keyboard_target.cc:78 +msgid "KeyboardTarget: no translation found for \"%1\"" +msgstr "KeyboardTarget: δεν ευÏέθη μετάφÏαση για \"%1\"" + +#: gtk_ardour/keyboard_target.cc:83 +msgid "KeyboardTarget: unknown action \"%1\"" +msgstr "KeyboardTarget: άγνωστη ενέÏγεια \"%1\"" + +#: gtk_ardour/keyboard_target.cc:248 +msgid "misformed binding node - ignored" +msgstr "παÏαμοÏφωμένος πομπός Î´ÎµÏƒÎ¼Î¿Ï - αγνοήθηκε" + +#: gtk_ardour/library_ui.cc:62 +msgid "Soundfile Library" +msgstr "Βιβλιοθήκη Soundfiles" + +#: gtk_ardour/library_ui.cc:63 +msgid "Filesystem" +msgstr "Filesystem" + +#: gtk_ardour/library_ui.cc:66 +msgid "Split Channels" +msgstr "ΔιαχωÏισμός Καναλιών" + +#: gtk_ardour/library_ui.cc:69 +msgid "ardour: soundfile selector" +msgstr "ardour: επιλογέας Soundfiles" + +#: gtk_ardour/library_ui.cc:430 +msgid "Add to Library..." +msgstr "ΠÏόσθεση στη Βιβλιοθήκη..." + +#: gtk_ardour/library_ui.cc:431 +msgid "Remove..." +msgstr "Απαλοιφή..." + +#: gtk_ardour/library_ui.cc:432 +msgid "Find..." +msgstr "ΕÏÏεση..." + +#: gtk_ardour/library_ui.cc:433 +msgid "Add Folder" +msgstr "ΠÏόσθεση Φακέλου" + +#: gtk_ardour/library_ui.cc:434 +msgid "Add audio file or directory" +msgstr "ΠÏόσθεση αÏχείου ήχου ή φακέλου" + +#: gtk_ardour/library_ui.cc:713 +msgid "Importing" +msgstr "Εισαγωγή εν εξελίξι" + +#: gtk_ardour/library_ui.cc:748 +msgid "%1 not added to database" +msgstr "%1 δεν Ï€Ïοστέθηκε στην database" + +#: gtk_ardour/library_ui.cc:767 +msgid "Folder name:" +msgstr "Όνομα φακέλου:" + +#: gtk_ardour/library_ui.cc:838 +msgid "Should not be reached" +msgstr "Δεν θα έπÏεπε να αγγιχτεί" + +#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096 +msgid "file \"%1\" could not be opened" +msgstr "το αÏχείο \"%1\" δεν γινόταν να ανοιχτεί" + +#: gtk_ardour/library_ui.cc:956 +msgid "Field" +msgstr "Πεδίο" + +#: gtk_ardour/library_ui.cc:957 +msgid "Value" +msgstr "Αξία" + +#: gtk_ardour/library_ui.cc:973 +msgid "Stop" +msgstr "ΠαÏση" + +#: gtk_ardour/library_ui.cc:974 +msgid "Add Field..." +msgstr "ΠÏόσθεση Πεδίου..." + +#: gtk_ardour/library_ui.cc:975 +msgid "Remove Field" +msgstr "Απαλοιφή Πεδίου" + +#: gtk_ardour/library_ui.cc:979 +msgid "Soundfile Info" +msgstr "ΠληÏοφοÏίες για το Soundfile" + +#: gtk_ardour/library_ui.cc:1106 +msgid "file \"%1\" appears not to be an audio file" +msgstr "" + +#: gtk_ardour/library_ui.cc:1159 +msgid "Could not read file: %1 (%2)." +msgstr "Δεν γινόταν να διαβαστεί το αÏχείο: %1 (%2)." + +#: gtk_ardour/library_ui.cc:1177 +msgid "Could not access soundfile: " +msgstr "Δεν γινόταν να διαβαστεί το soundfile: " + +#: gtk_ardour/library_ui.cc:1222 +msgid "Field name:" +msgstr "Όνομα Πεδίου:" + +#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367 +msgid "Field value:" +msgstr "Αξία Πεδίου:" + +#: gtk_ardour/library_ui.cc:1295 +msgid "Find" +msgstr "ΕÏÏεση" + +#: gtk_ardour/library_ui.cc:1296 +msgid "AND" +msgstr "AND" + +#: gtk_ardour/library_ui.cc:1297 +msgid "OR" +msgstr "OR" + +#: gtk_ardour/library_ui.cc:1300 +msgid "ardour: locate soundfiles" +msgstr "ardour: εÏÏεση soundfiles" + +#: gtk_ardour/library_ui.cc:1426 +msgid "Results" +msgstr "Αποτελέσματα" + +#: gtk_ardour/library_ui.cc:1427 +msgid "Uris" +msgstr "Uris" + +#: gtk_ardour/library_ui.cc:1439 +msgid "Create multi-channel region" +msgstr "ΔημιουÏγία πολυκάναλης πεÏιοχής" + +#: gtk_ardour/library_ui.cc:1442 +msgid "Ardour: Search Results" +msgstr "Ardour: Αποτελέσματα Αναζητήσεως" + +#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50 +msgid "Set" +msgstr "Θέση" + +#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51 +msgid "Go" +msgstr "Πήγαινε" + +#: gtk_ardour/location_ui.cc:54 +msgid "CD" +msgstr "CD" + +#: gtk_ardour/location_ui.cc:55 +msgid "Hidden" +msgstr "ΚÏυμμένο" + +#: gtk_ardour/location_ui.cc:57 +msgid "SCMS" +msgstr "" + +#: gtk_ardour/location_ui.cc:58 +msgid "Pre-Emphasis" +msgstr "" + +#: gtk_ardour/location_ui.cc:592 +msgid "Add New Location" +msgstr "ΠÏόσθεση νέας τοποθεσίας" + +#: gtk_ardour/location_ui.cc:593 +msgid "Add New Range" +msgstr "ΠÏόσθεση νέου διαστήματος" + +#: gtk_ardour/location_ui.cc:597 +msgid "ardour: locations" +msgstr "ardour: τοποθεσίες" + +#: gtk_ardour/location_ui.cc:598 +msgid "ardour_locations" +msgstr "ardour_τοποθεσίες" + +#: gtk_ardour/location_ui.cc:629 +#, fuzzy +msgid "Location (CD Index) Markers" +msgstr "Στίγματα Τοποθεσίας" + +#: gtk_ardour/location_ui.cc:649 +#, fuzzy +msgid "Range (CD Track) Markers" +msgstr "Στίγματα διαστημάτων" + +#: gtk_ardour/location_ui.cc:814 +msgid "add range marker" +msgstr "Ï€Ïόσθεση στίγματος διαστήματος" + +#: gtk_ardour/main.cc:76 +msgid "ardour is killing itself for a clean exit\n" +msgstr "Ο ardour σκοτώνει τον εαυτό του για καθαÏή έξοδο\n" + +#: gtk_ardour/main.cc:85 +msgid "stopping user interface\n" +msgstr "παÏση του user interface\n" + +#: gtk_ardour/main.cc:104 +#, fuzzy, c-format +msgid "%d(%d): received signal %d\n" +msgstr "%d: εδέχθη σήμα %d\n" + +#: gtk_ardour/main.cc:190 +msgid "cannot become new process group leader (%1)" +msgstr "" + +#: gtk_ardour/main.cc:217 +msgid "cannot setup signal handling for %1" +msgstr "δεν γίνεται να διαμοÏφώθεί η διαχείÏηση σημάτων για %1" + +#: gtk_ardour/main.cc:228 +msgid "cannot set default signal mask (%1)" +msgstr "δεν γίνεται να διαμοÏφώθεί η Ï€ÏοκαθοÏισμένη μάσκα σημάτων (%1)" + +#: gtk_ardour/main.cc:253 +#, fuzzy +msgid "" +"Without a UI style file, ardour will look strange.\n" +" Please set ARDOUR_UI_RC to point to a valid UI style file" +msgstr "" +"Δίχως αÏχείο εμφάνισεως UI, ο ardour θα φαίνεται παÏάξενα.\n" +"ΠαÏακαλώ θέστε το ARDOUR_UI_RC να δείχνει σε ενεÏγό αÏχείο εμφανίσεως UI" + +#: gtk_ardour/main.cc:292 +msgid "" +"Ardour could not connect to JACK.\n" +"There are several possible reasons:\n" +"\n" +"1) JACK is not running.\n" +"2) JACK is running as another user, perhaps root.\n" +"3) There is already another client called \"ardour\".\n" +"\n" +"Please consider the possibilities, and perhaps (re)start JACK." +msgstr "" +"Ο Ardour δεν μπόÏεσε να συνδεθεί στον JACK.\n" +"ΥπάÏχουν διάφοÏοι πιθανοί λόγοι:\n" +"\n" +"1) Ο JACK δεν Ï„Ïέχει.\n" +"2) JACK Ï„Ïέχει σαν άλλος ΧÏήστης, ίσως σαν root.\n" +"3) ΥπάÏχει ήδη άλλο Ï€ÏόγÏαμμα με το όνομα \"ardour\".\n" +"\n" +"ΠαÏακαλώ αναλογιστείτε τις πιθανότητες, και ίσως (ξανα)ξεκινήστε τον JACK." + +#: gtk_ardour/main.cc:305 +msgid "ardour: unplugged" +msgstr "ardour: unplugged" + +#: gtk_ardour/main.cc:363 +msgid "Ardour/GTK " +msgstr "Ardour/GTK " + +#: gtk_ardour/main.cc:365 +msgid "" +"\n" +" (built using " +msgstr "" + +#: gtk_ardour/main.cc:369 +#, fuzzy +msgid " with libardour " +msgstr " Ï„Ïέχοντας με libardour " + +#: gtk_ardour/main.cc:374 +msgid " and GCC version " +msgstr "" + +#: gtk_ardour/main.cc:384 +#, fuzzy +msgid "Copyright (C) 1999-2005 Paul Davis" +msgstr "Πνευματικα Δικαιώματα 1999-2004 Paul Davis" + +#: gtk_ardour/main.cc:385 +msgid "" +"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel " +"Baker" +msgstr "" + +#: gtk_ardour/main.cc:387 +msgid "Ardour comes with ABSOLUTELY NO WARRANTY" +msgstr "Ο Ardour έÏχεται με απολÏτως ΚΑΜΙΑ ΕΓΓΥΗΣΗ" + +#: gtk_ardour/main.cc:388 +msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +msgstr "" + +#: gtk_ardour/main.cc:389 +msgid "This is free software, and you are welcome to redistribute it " +msgstr "" +"Το παÏόν είναι ελεÏθεÏο λογισμικό, είστε ελεÏθεÏοι να το επαναδιανείμετε " + +#: gtk_ardour/main.cc:390 +#, fuzzy +msgid "under certain conditions; see the source for copying conditions." +msgstr "υπό οÏισμένους ÏŒÏους, ανατÏέξτε στο αÏχείο COPYING για λεπτομέÏειες" + +#: gtk_ardour/main.cc:399 +msgid "could not create ARDOUR GUI" +msgstr "δεν γινόταν να δημιουÏγηθεί ARDOUR GUI" + +#: gtk_ardour/main.cc:419 +msgid "Could not connect to JACK server as \"%1\"" +msgstr "Δεν γινόταν να συνδεθώ στον JACK server σαν \"%1\"" + +#: gtk_ardour/main.cc:424 +msgid "could not initialize Ardour." +msgstr "δεν γινόταν να εκκινηθεί ο Ardour." + +#: gtk_ardour/main.cc:435 +msgid "could not load command line session \"%1\"" +msgstr "δεν γινόταν να φοÏτωθεί η συνεδÏία γÏαμμής εντολών \"%1\"" + +#: gtk_ardour/main.cc:455 +msgid "" +"\n" +"\n" +"A session named \"%1\" already exists.\n" +"To avoid this message, start ardour as \"ardour %1" +msgstr "" + +#: gtk_ardour/main.cc:466 +msgid "" +"\n" +"\n" +"No session named \"%1\" exists.\n" +"To create it from the command line, start ardour as \"ardour --new %1" +msgstr "" + +#: gtk_ardour/marker.cc:354 +#, fuzzy +msgid "MarkerText" +msgstr "Στίγματα" + +#: gtk_ardour/marker_time_axis.cc:271 +#, fuzzy +msgid "Remove Marker" +msgstr "απαλοιφή στίγματος" + +#: gtk_ardour/marker_time_axis.cc:273 +#, fuzzy +msgid "Marker" +msgstr "Στίγματα" + +#: gtk_ardour/meter_bridge.cc:74 +msgid "ardour: meter bridge" +msgstr "ardour: γέφυÏα μετÏήσεων" + +#: gtk_ardour/meter_bridge.cc:75 +msgid "ardour_meter_bridge" +msgstr "ardour_γέφυÏα_μετÏήσεων" + +#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93 +#, c-format +msgid "# of %u-sample overs" +msgstr "# από %u-sample overs" + +#: gtk_ardour/meter_bridge_strip.cc:219 +msgid "New name for meter:" +msgstr "Îέο όνομα για μετÏητή:" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507 +#: gtk_ardour/region_editor.cc:45 +msgid "mute" +msgstr "σιγή" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508 +msgid "solo" +msgstr "σόλο" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506 +msgid "RECORD" +msgstr "ΕΓΓΡΑΦΗ" + +#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514 +msgid "polarity" +msgstr "πολικότητα" + +#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509 +msgid "comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810 +msgid "INPUT" +msgstr "ΕΙΣΟΔΟΣ" + +#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831 +msgid "OUTPUT" +msgstr "ΕΞΟΔΟΣ" + +#: gtk_ardour/mixer_strip.cc:173 +msgid "Pan automation mode" +msgstr "ΛειτουÏγία Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Pan" + +#: gtk_ardour/mixer_strip.cc:174 +msgid "Gain automation mode" +msgstr "ΛειτουÏγία Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Gain" + +#: gtk_ardour/mixer_strip.cc:176 +msgid "Pan automation type" +msgstr "ΤÏπος Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Pan" + +#: gtk_ardour/mixer_strip.cc:177 +msgid "Gain automation type" +msgstr "ΤÏπος Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Gain" + +#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232 +#: gtk_ardour/mixer_strip.cc:979 +msgid "trim" +msgstr "ισοστάθμιση" + +#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233 +#: gtk_ardour/mixer_strip.cc:983 +msgid "abs" +msgstr "abs" + +#: gtk_ardour/mixer_strip.cc:240 +msgid "gain automation mode" +msgstr "ΛειτουÏγία Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï gain" + +#: gtk_ardour/mixer_strip.cc:241 +msgid "pan automation mode" +msgstr "ΛειτουÏγία Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï pan" + +#: gtk_ardour/mixer_strip.cc:242 +msgid "gain automation state" +msgstr "Κατάσταση Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï gain" + +#: gtk_ardour/mixer_strip.cc:243 +msgid "pan automation state" +msgstr "Κατάσταση Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï pan" + +#: gtk_ardour/mixer_strip.cc:259 +msgid "varispeed" +msgstr "μεταβλητή ταχÏτητα" + +#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174 +msgid "click to add/edit comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:463 +msgid "unknown strip width \"%1\" in XML GUI information" +msgstr "άγνωστο εÏÏος διαδÏόμου \"%1\" στις πληÏοφοÏίες του XML GUI" + +#: gtk_ardour/mixer_strip.cc:522 +msgid "REC" +msgstr "REC" + +#: gtk_ardour/mixer_strip.cc:525 +#, fuzzy +msgid "cmt" +msgstr "κοπή" + +#: gtk_ardour/mixer_strip.cc:530 +msgid "pol" +msgstr "πολ" + +#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620 +#: gtk_ardour/redirect_box.cc:1180 +msgid "Not connected to JACK - no I/O changes are possible" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667 +msgid "could not register new ports required for that connection" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:813 +msgid "IN" +msgstr "IN" + +#: gtk_ardour/mixer_strip.cc:834 +msgid "OUT" +msgstr "OUT" + +#: gtk_ardour/mixer_strip.cc:950 +msgid "aplay" +msgstr "aplay" + +#: gtk_ardour/mixer_strip.cc:956 +msgid "awrite" +msgstr "awrite" + +#: gtk_ardour/mixer_strip.cc:1134 +#, fuzzy +msgid ": comment editor" +msgstr "UI: Ο 'editor' δεν μποÏεί να εγεÏθεί" + +#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224 +msgid "no group" +msgstr "καμία ομάδα" + +#: gtk_ardour/mixer_strip.cc:1227 +msgid "~G" +msgstr "~G" + +#: gtk_ardour/mixer_ui.cc:52 +msgid "Strips" +msgstr "ΔιάδÏομοι" + +#: gtk_ardour/mixer_ui.cc:56 +msgid "Snapshots" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:61 +msgid "***" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17 +#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144 +#: gtk_ardour/tempo_dialog.cc:162 +msgid "Bar" +msgstr "ΜπάÏα" + +#: gtk_ardour/mixer_ui.cc:121 +msgid "Mix Groups" +msgstr "Ανάμειξη ομάδων" + +#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373 +msgid "ardour: mixer" +msgstr "ardour: μίκτης" + +#: gtk_ardour/mixer_ui.cc:192 +msgid "ardour_mixer" +msgstr "ardour_μίκτης" + +#: gtk_ardour/mixer_ui.cc:342 +msgid "ardour: mixer: " +msgstr "ardour: μίκτης: " + +#: gtk_ardour/mixer_ui.cc:641 +msgid "signal" +msgstr "σήμα" + +#: gtk_ardour/mixer_ui.cc:672 +msgid "Show All AudioTrack MixerStrips" +msgstr "Ανάδειξη όλων των ΔιαδÏόμωνΜίξεως των καναλιών" + +#: gtk_ardour/mixer_ui.cc:673 +msgid "Hide All AudioTrack MixerStrips" +msgstr "ΑπόκÏυψη όλων των ΔιαδÏόμωνΜίξεως των καναλιών" + +#: gtk_ardour/mixer_ui.cc:674 +msgid "Show All AudioBus MixerStrips" +msgstr "Ανάδειξη όλων των ΔιαδÏόμωνΜίξεως των διαÏλων" + +#: gtk_ardour/mixer_ui.cc:675 +msgid "Hide All AudioBus MixerStrips" +msgstr "ΑπόκÏυψη όλων των ΔιαδÏόμωνΜίξεως των διαÏλων" + +#: gtk_ardour/mixer_ui.cc:687 +msgid "track display list item for renamed strip not found!" +msgstr "Λίστα αναδείξεως καναλιών για μετονομασμένο διάδÏομο δεν ευÏέθη!" + +#: gtk_ardour/mixer_ui.cc:700 +msgid "Name for new mix group" +msgstr "Όνομα για νέα ομάδα μίξεως" + +#: gtk_ardour/new_session_dialog.cc:39 +msgid "Session name:" +msgstr "Όνομα συνεδÏίας:" + +#: gtk_ardour/new_session_dialog.cc:39 +msgid "Create" +msgstr "ΔημιουÏγία" + +#: gtk_ardour/new_session_dialog.cc:40 +msgid "use control outs" +msgstr "χÏήση των control outs" + +#: gtk_ardour/new_session_dialog.cc:41 +msgid "use master outs" +msgstr "χÏήση των master outs" + +#: gtk_ardour/new_session_dialog.cc:42 +msgid "automatically connect track inputs to physical ports" +msgstr "αυτόματη σÏνδεση inputs καναλιών σε φυσικές θÏÏες" + +#: gtk_ardour/new_session_dialog.cc:43 +msgid "automatically connect track outputs to master outs" +msgstr "αυτόματη σÏνδεση outputs καναλιών σε master outs" + +#: gtk_ardour/new_session_dialog.cc:44 +msgid "automatically connect track outputs to physical ports" +msgstr "αυτόματη σÏνδεση outputs καναλιών σε φυσικές θÏÏες" + +#: gtk_ardour/new_session_dialog.cc:45 +msgid "manually connect track outputs" +msgstr "χειÏοκίνητη σÏνδεση των outputs των καναλιών" + +#: gtk_ardour/new_session_dialog.cc:50 +msgid "Advanced..." +msgstr "ΠÏοχωÏημένα..." + +#: gtk_ardour/new_session_dialog.cc:52 +msgid "show again" +msgstr "δείξε πάλι" + +#: gtk_ardour/new_session_dialog.cc:55 +msgid "Hardware Inputs: use" +msgstr "Hardware Είσοδοι: χÏήση" + +#: gtk_ardour/new_session_dialog.cc:56 +msgid "Hardware Outputs: use" +msgstr "Hardware Έξοδοι: χÏήση" + +#: gtk_ardour/new_session_dialog.cc:62 +msgid "new session setup" +msgstr "νέα δαÏÏÏθμιση συνεδÏίας" + +#: gtk_ardour/new_session_dialog.cc:63 +msgid "ardour_new_session" +msgstr "ardour_νέα_συνεδÏία" + +#: gtk_ardour/new_session_dialog.cc:72 +msgid "This session will playback and record at %1 Hz" +msgstr "Αυτή η συνεδÏία θα αναπαÏάγει και θα εγγÏάφει στα %1 Hz" + +#: gtk_ardour/new_session_dialog.cc:74 +msgid "" +"This rate is set by JACK and cannot be changed.\n" +"If you want to use a different sample rate\n" +"please exit and restart JACK" +msgstr "" +"Αυτος ο 'Ïυθμός'(sample rate) τίθεται από τον JACK και δεν μποÏεί να " +"αλλάξει.\n" +"Αν επιθυμείτε να θέσετε διαφοÏετικό 'Ïυθμό'\n" +"παÏακαλώ βγείτε και επανεκκινήστε τον JACK" + +#: gtk_ardour/new_session_dialog.cc:155 +msgid "Session template" +msgstr "ΠÏοσχέδιο συνεδÏίας" + +#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20 +#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146 +#: gtk_ardour/tempo_dialog.cc:164 +msgid "Location" +msgstr "Τοποθεσία" + +#: gtk_ardour/new_session_dialog.cc:178 +msgid "Configuration" +msgstr "Διάταξη" + +#: gtk_ardour/new_session_dialog.cc:269 +msgid "blank" +msgstr "κενό" + +#: gtk_ardour/new_session_dialog.cc:328 +msgid "No template - create tracks/busses manually" +msgstr "ΧωÏίς Ï€Ïοσχέδιο - δημιουÏγία καναλιών/διαÏλων χειÏοκίνητα" + +#: gtk_ardour/new_session_dialog.cc:337 +msgid "No template" +msgstr "ΧωÏίς Ï€Ïοσχέδιο" + +#: gtk_ardour/option_editor.cc:48 +msgid "Internal" +msgstr "ΕσωτεÏικό" + +#: gtk_ardour/option_editor.cc:49 +msgid "Slave to MTC" +msgstr "Slave στον MTC" + +#: gtk_ardour/option_editor.cc:50 +msgid "Sync with JACK" +msgstr "ΣÏγχÏονος με τον JACK" + +#: gtk_ardour/option_editor.cc:51 +msgid "never used but stops crashes" +msgstr "αχÏησιμοποίητο αλλά σταματά τα crashes" + +#: gtk_ardour/option_editor.cc:56 +#, fuzzy +msgid "Later regions are higher" +msgstr "Υποβίβαση πεÏιοχής κατά ένα στÏώμα" + +#: gtk_ardour/option_editor.cc:57 +msgid "Most recently added/moved/trimmed regions are higher" +msgstr "" + +#: gtk_ardour/option_editor.cc:58 +#, fuzzy +msgid "Most recently added regions are higher" +msgstr "Υποβίβαση πεÏιοχής κατά ένα στÏώμα" + +#: gtk_ardour/option_editor.cc:63 +#, fuzzy +msgid "Span entire region overlap" +msgstr "ΑνόÏθωση πεÏιοχής κατά ένα στÏώμα" + +#: gtk_ardour/option_editor.cc:64 +msgid "Short fades at the start of the overlap" +msgstr "" + +#: gtk_ardour/option_editor.cc:82 +#, fuzzy +msgid "Automatically create crossfades" +msgstr "Αυτόματο crossfade στα overlap" + +#: gtk_ardour/option_editor.cc:83 +msgid "New full-overlap crossfades are unmuted" +msgstr "" + +#: gtk_ardour/option_editor.cc:84 +#, fuzzy +msgid "Region layering mode" +msgstr "Τέλη ΠεÏιοχών" + +#: gtk_ardour/option_editor.cc:85 +#, fuzzy +msgid "Crossfade model" +msgstr "Crossfade" + +#: gtk_ardour/option_editor.cc:90 +msgid "Latched solo" +msgstr "ΠÏοσκολλημένο σόλο" + +#: gtk_ardour/option_editor.cc:91 +msgid "Solo via bus" +msgstr "Solo μέσω διαÏλου" + +#: gtk_ardour/option_editor.cc:96 +msgid "Show waveforms while recording" +msgstr "Ανάδειξη κυματομοÏφών κατά την εγγÏαφή" + +#: gtk_ardour/option_editor.cc:97 +msgid "Narrow mixer strips" +msgstr "Στενοί διάδÏομοι μείκτη" + +#: gtk_ardour/option_editor.cc:98 +msgid "Show measure lines" +msgstr "Ανάδειξη γÏαμμών μετÏήσεων" + +#: gtk_ardour/option_editor.cc:99 +msgid "Follow playhead" +msgstr "Ακολουθία ΑναπαÏαγωγέα" + +#: gtk_ardour/option_editor.cc:103 +msgid "Send MTC" +msgstr "Αποστολή MTC" + +#: gtk_ardour/option_editor.cc:104 +msgid "Send MMC" +msgstr "Αποστολή MMC" + +#: gtk_ardour/option_editor.cc:105 +msgid "JACK time master" +msgstr "JACK master χÏόνου" + +#: gtk_ardour/option_editor.cc:107 +#, fuzzy +msgid "SMPTE offset is negative" +msgstr "SMPTE ΈναÏξη" + +#: gtk_ardour/option_editor.cc:111 +msgid "Send MIDI parameter feedback" +msgstr "" + +#: gtk_ardour/option_editor.cc:112 +msgid "MIDI parameter control" +msgstr "" + +#: gtk_ardour/option_editor.cc:113 +#, fuzzy +msgid "MMC control" +msgstr "MMC ΘÏÏα" + +#: gtk_ardour/option_editor.cc:131 +#, fuzzy +msgid "Auto-connect new track inputs to hardware" +msgstr "Αυτο-σÏνδεση νέων καναλιών" + +#: gtk_ardour/option_editor.cc:132 +#, fuzzy +msgid "Auto-connect new track outputs to hardware" +msgstr "Αυτο-σÏνδεση νέων καναλιών" + +#: gtk_ardour/option_editor.cc:133 +#, fuzzy +msgid "Auto-connect new track outputs to master bus" +msgstr "αυτόματη σÏνδεση outputs καναλιών σε master outs" + +#: gtk_ardour/option_editor.cc:134 +#, fuzzy +msgid "Manually connect new track outputs" +msgstr "χειÏοκίνητη σÏνδεση των outputs των καναλιών" + +#: gtk_ardour/option_editor.cc:135 +msgid "Use Hardware Monitoring" +msgstr "ΧÏήση Hardware Monitoring" + +#: gtk_ardour/option_editor.cc:136 +msgid "Use Software Monitoring" +msgstr "ΧÏήση Software Monitoring" + +#: gtk_ardour/option_editor.cc:137 +msgid "Stop plugins with transport" +msgstr "Λήξη των plugins με την παÏση" + +#: gtk_ardour/option_editor.cc:138 +msgid "Run plugins while recording" +msgstr "ΛειτουÏγία plugins κατα την εγγÏαφή" + +#: gtk_ardour/option_editor.cc:139 +#, fuzzy +msgid "Verify remove last capture" +msgstr "Απαλοιφή τελευταίας λήψης" + +#: gtk_ardour/option_editor.cc:140 +msgid "Stop recording on xrun" +msgstr "ΠαÏση εγγÏαφής στα xrun" + +#: gtk_ardour/option_editor.cc:141 +msgid "Stop transport at end of session" +msgstr "Στάση αναπαÏαγωγέα στο τέλος της συνεδÏίας" + +#: gtk_ardour/option_editor.cc:142 +msgid "Debug keyboard events" +msgstr "Debug γεγονότα πληκτÏολογίου" + +#: gtk_ardour/option_editor.cc:143 +msgid "-12dB gain reduction for ffwd/rew" +msgstr "" + +#: gtk_ardour/option_editor.cc:152 +msgid "ardour: options editor" +msgstr "ardour: επεξεÏγαστής Ïυθμίσεων" + +#: gtk_ardour/option_editor.cc:153 +msgid "ardour_option_editor" +msgstr "ardour_επεξεÏγαστής_Ïυθμίσεων" + +#: gtk_ardour/option_editor.cc:183 +msgid "Misc" +msgstr "ΔιάφοÏα" + +#: gtk_ardour/option_editor.cc:184 +msgid "Sync" +msgstr "Sync" + +#: gtk_ardour/option_editor.cc:185 +msgid "Paths/Files" +msgstr "Paths/ΑÏχεία" + +#: gtk_ardour/option_editor.cc:186 +msgid "Display" +msgstr "Απεικόνιση" + +#: gtk_ardour/option_editor.cc:187 +msgid "Kbd/Mouse" +msgstr "ΠλκτÏ/Ποντίκι" + +#: gtk_ardour/option_editor.cc:188 +msgid "Click" +msgstr "ΜετÏονόμος" + +#: gtk_ardour/option_editor.cc:190 +msgid "Layers & Fades" +msgstr "" + +#: gtk_ardour/option_editor.cc:195 +msgid "MIDI" +msgstr "MIDI" + +#: gtk_ardour/option_editor.cc:268 +msgid "24 FPS" +msgstr "24 FPS" + +#: gtk_ardour/option_editor.cc:270 +msgid "25 FPS" +msgstr "25 FPS" + +#: gtk_ardour/option_editor.cc:272 +#, fuzzy +msgid "30 FPS" +msgstr "30 FPS drop" + +#: gtk_ardour/option_editor.cc:278 +msgid "30 FPS drop" +msgstr "30 FPS drop" + +#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379 +#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736 +#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800 +msgid "Medium" +msgstr "" + +#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738 +#: gtk_ardour/option_editor.cc:804 +#, fuzzy +msgid "Faster" +msgstr "ΤαχÏ" + +#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714 +#: gtk_ardour/option_editor.cc:776 +#, fuzzy +msgid "Short" +msgstr "θÏÏα" + +#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716 +#: gtk_ardour/option_editor.cc:780 +msgid "Long" +msgstr "" + +#: gtk_ardour/option_editor.cc:396 +msgid "Broadcast WAVE/floating point" +msgstr "Broadcast WAVE/μεταβλητής υποδ/λής" + +#: gtk_ardour/option_editor.cc:397 +msgid "WAVE/floating point" +msgstr "WAVE/μεταβλητής υποδ/λής" + +#: gtk_ardour/option_editor.cc:417 +msgid "session RAID path" +msgstr "RAID path συνεδÏίας" + +#: gtk_ardour/option_editor.cc:422 +msgid "Native Format" +msgstr "Εντόπιο Format" + +#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460 +#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409 +msgid "internal" +msgstr "εσωτεÏικό" + +#: gtk_ardour/option_editor.cc:537 +msgid "Short crossfade length (msecs)" +msgstr "" + +#: gtk_ardour/option_editor.cc:710 +msgid "Meter Peak Hold" +msgstr "" + +#: gtk_ardour/option_editor.cc:730 +msgid "Meter Falloff" +msgstr "" + +#: gtk_ardour/option_editor.cc:847 +msgid "Positional Sync" +msgstr "Τοποθεσιακό Sync" + +#: gtk_ardour/option_editor.cc:902 +msgid "SMPTE Frames/second" +msgstr "SMPTE ΚαÏέ/δεÏτεÏα" + +#: gtk_ardour/option_editor.cc:903 +msgid "SMPTE Offset" +msgstr "SMPTE ΈναÏξη" + +#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013 +#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211 +#, fuzzy +msgid "online" +msgstr "γÏαμμική" + +#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014 +#: gtk_ardour/option_editor.cc:1208 +#, fuzzy +msgid "offline" +msgstr "γÏαμμική" + +#: gtk_ardour/option_editor.cc:1319 +msgid "Use as click" +msgstr "ΧÏήση όπως στο μετÏονόμο" + +#: gtk_ardour/option_editor.cc:1344 +msgid "Use as click emphasis" +msgstr "Έμφαση χÏήσεως όπως στο μετÏονόμο" + +#: gtk_ardour/option_editor.cc:1478 +msgid "--unknown--" +msgstr "--άγνωστο--" + +#: gtk_ardour/option_editor.cc:1595 +msgid "Click audio file" +msgstr "ΑÏχείο ήχου ΜετÏονόμου" + +#: gtk_ardour/option_editor.cc:1601 +msgid "Click emphasis audiofile" +msgstr "ΑÏχείο ήχου εμφάσεως ΜετÏονόμου" + +#: gtk_ardour/option_editor.cc:1638 +msgid "" +"The auditioner is a dedicated mixer strip used\n" +"for listening to specific regions outside the context\n" +"of the overall mix. It can be connected just like any\n" +"other mixer strip." +msgstr "" +"Ο 'ακÏοατής' είναι ένας αφοσιωμένος διάδÏομος μίξεως που χÏησιμοποιείται\n" +"για ακÏόαση συγκεκÏιμένων πεÏιοχών εκτός\n" +"του Î³ÎµÎ½Î¹ÎºÎ¿Ï Î¼Î¹Î¾Î±Ïίσματος. ΜποÏεί να συνδεθεί σαν άλλος ένας\n" +"διάδÏομος μίξεως ή κανάλι." + +#: gtk_ardour/option_editor.cc:1887 +msgid "Edit using" +msgstr "ΕπεξεÏγασία με" + +#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924 +msgid "+ button" +msgstr "+ κουμπί" + +#: gtk_ardour/option_editor.cc:1917 +msgid "Delete using" +msgstr "ΔιαγÏαφή με" + +#: gtk_ardour/option_editor.cc:1947 +msgid "Ignore snap using" +msgstr "Άγνοια έλξεως με" + +#: gtk_ardour/opts.cc:46 +msgid "Usage: " +msgstr "ΧÏήση: " + +#: gtk_ardour/opts.cc:47 +msgid " -v, --version Show version information\n" +msgstr " -v, --version ΠληÏοφοÏίες εκδόσεως\n" + +#: gtk_ardour/opts.cc:48 +msgid " -h, --help Print this message\n" +msgstr " -h, --help ΠÏοβολή του παÏόντος\n" + +#: gtk_ardour/opts.cc:49 +msgid "" +" -b, --bindings Print all possible keyboard binding " +"names\n" +msgstr "" +" -b, --bindings ΠÏοβολή όλων των πιθανών δεσμών " +"πληκτÏολογίου ονόματα\n" + +#: gtk_ardour/opts.cc:50 +#, fuzzy +msgid " -n, --show-splash Show splash screen\n" +msgstr " -n, --no-splash Μήν δείξεις την εισαγωγική εικόνα\n" + +#: gtk_ardour/opts.cc:51 +#, fuzzy +msgid "" +" -c, --name name Use a specific jack client name, default " +"is ardour\n" +msgstr "" +" -c, --jack-client-name name ΧÏήση συγκεκÏιμένου ονόματος για τον " +"jack, το Ï€ÏοκαθοÏισμένο είναι ardour\n" + +#: gtk_ardour/opts.cc:52 +#, fuzzy +msgid "" +" -N, --new session-name Create a new session from the command " +"line\n" +msgstr " [όνομα-συνεδÏίας] Όνομα συνεδÏίας Ï€Ïος φόÏτωση\n" + +#: gtk_ardour/opts.cc:53 +msgid "" +" -o, --use-hw-optimizations Try to use h/w specific optimizations\n" +msgstr "" + +#: gtk_ardour/opts.cc:55 +#, fuzzy +msgid " -V, --novst Do not use VST support\n" +msgstr " -n, --no-splash Μήν δείξεις την εισαγωγική εικόνα\n" + +#: gtk_ardour/opts.cc:57 +msgid " [session-name] Name of session to load\n" +msgstr " [όνομα-συνεδÏίας] Όνομα συνεδÏίας Ï€Ïος φόÏτωση\n" + +#: gtk_ardour/opts.cc:58 +msgid " -C, --curvetest filename Curve algorithm debugger\n" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:58 +msgid "You can't graphically edit panning of more than stream" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:78 +#, fuzzy +msgid "add pan automation event" +msgstr "Ï€Ïόσθεση συμβάντος Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï ÏƒÎµ " + +#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441 +#, fuzzy +msgid "Bypass" +msgstr "bypass" + +#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222 +#, fuzzy +msgid "link" +msgstr "in" + +#: gtk_ardour/panner_ui.cc:103 +msgid "panning link control" +msgstr "έλεγχος panning link" + +#: gtk_ardour/panner_ui.cc:105 +msgid "panning link direction" +msgstr "κατεÏθυνση panning link" + +#: gtk_ardour/panner_ui.cc:232 +msgid "L" +msgstr "L" + +#: gtk_ardour/panner_ui.cc:344 +#, c-format +msgid "panner for channel %u" +msgstr "panner για το κανάλι %u" + +#: gtk_ardour/panner_ui.cc:451 +#, fuzzy +msgid "Reset all" +msgstr "Επιλογή όλων" + +#: gtk_ardour/playlist_selector.cc:46 +msgid "Playlists grouped by track" +msgstr "" + +#: gtk_ardour/playlist_selector.cc:53 +#, fuzzy +msgid "close" +msgstr "Κλείσιμο" + +#: gtk_ardour/playlist_selector.cc:59 +#, fuzzy +msgid "ardour: playlists" +msgstr "ardour: plugins" + +#: gtk_ardour/playlist_selector.cc:104 +#, fuzzy +msgid "ardour: playlist for " +msgstr "ardour: επεξεÏγαστής: " + +#: gtk_ardour/playlist_selector.cc:122 +#, fuzzy +msgid "Other tracks" +msgstr "νÏξη καναλιοÏ" + +#: gtk_ardour/playlist_selector.cc:138 +msgid "unassigned" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:41 +msgid "Available LADSPA plugins" +msgstr "Διαθέσιμα LADSPA plugins" + +#: gtk_ardour/plugin_selector.cc:42 +msgid "Type" +msgstr "ΤÏπωση" + +#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51 +msgid "# Inputs" +msgstr "# Είσοδοι" + +#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52 +msgid "# Outputs" +msgstr "# Έξοδοι" + +#: gtk_ardour/plugin_selector.cc:50 +msgid "Available VST plugins" +msgstr "Διαθέσιμα VST plugins" + +#: gtk_ardour/plugin_selector.cc:58 +msgid "To be added" +msgstr "ΠÏόκειται να Ï€ÏοστεθοÏν" + +#: gtk_ardour/plugin_selector.cc:72 +msgid "ardour: plugins" +msgstr "ardour: plugins" + +#: gtk_ardour/plugin_selector.cc:82 +msgid "Add a plugin to the effect list" +msgstr "ΠÏόσθεση plugin στη λίστα των εφφέ" + +#: gtk_ardour/plugin_selector.cc:84 +msgid "Remove a plugin from the effect list" +msgstr "Απαλοιφή plugin από τη λίστα των εφφέ" + +#: gtk_ardour/plugin_selector.cc:88 +msgid "Update" +msgstr "Ανανέωση" + +#: gtk_ardour/plugin_selector.cc:89 +msgid "Update available plugins" +msgstr "Ανανέωση διαθέσιμων plugins" + +#: gtk_ardour/plugin_selector.cc:110 +msgid "LADSPA" +msgstr "LADSPA" + +#: gtk_ardour/plugin_selector.cc:113 +msgid "VST" +msgstr "VST" + +#: gtk_ardour/plugin_ui.cc:83 +msgid "" +"unknown type of editor-supplying plugin (note: no VST support in this " +"version of ardour)" +msgstr "" +"άγνωστος Ï„Ïπος Ï€Ïομηθευμένου plugin για τον editor(σημείωση: δεν υπάÏχει " +"υποστήÏιξη VST στην παÏοÏσα έκδοση του ardour)" + +#: gtk_ardour/plugin_ui.cc:269 +msgid "Plugin Editor: could not build control element for port %1" +msgstr "" +"ΕπεξεÏγαστής Plugin: δεν μπόÏεσα να κτίσω στοιχείο ελέγχου για τη θÏÏα %1" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "in" +msgstr "in" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "ins" +msgstr "ins" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "out" +msgstr "out" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "outs" +msgstr "outs" + +#: gtk_ardour/plugin_ui.cc:382 +msgid "automation control" +msgstr "έλεγχος αυτοματισμοÏ" + +#: gtk_ardour/plugin_ui.cc:869 +msgid "save" +msgstr "αποθήκευση" + +#: gtk_ardour/plugin_ui.cc:870 +msgid "bypass" +msgstr "bypass" + +#: gtk_ardour/plugin_ui.cc:892 +msgid "Plugin preset %1 not found" +msgstr "ΠÏο-ÏÏθμιση plugin %1 δεν ευÏέθη" + +#: gtk_ardour/plugin_ui.cc:903 +msgid "Name for plugin settings:" +msgstr "Όνομα για Ïυθμίσεις του plugin:" + +#: gtk_ardour/redirect_automation_line.cc:53 +msgid "redirect automation created for non-plugin" +msgstr "Ï€Ïοώθηση Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï Î´Î·Î¼Î¹Î¿Ï…Ïγημένου για non-plugin" + +#: gtk_ardour/redirect_automation_time_axis.cc:92 +msgid "add automation event to " +msgstr "Ï€Ïόσθεση συμβάντος Î±Ï…Ï„Î¿Î¼Î±Ï„Î¹ÏƒÎ¼Î¿Ï ÏƒÎµ " + +#: gtk_ardour/redirect_box.cc:213 +msgid "New send" +msgstr "Nέο send" + +#: gtk_ardour/redirect_box.cc:214 +msgid "Show send controls" +msgstr "Ανάδειξη Ïυθμίσεων send" + +#: gtk_ardour/redirect_box.cc:360 +msgid "New Plugin ..." +msgstr "Îέο Plugin ..." + +#: gtk_ardour/redirect_box.cc:361 +msgid "New Insert" +msgstr "Îέο ΠÏοσθήκη" + +#: gtk_ardour/redirect_box.cc:362 +msgid "New Send ..." +msgstr "Îέο Send ..." + +#: gtk_ardour/redirect_box.cc:380 +msgid "Select all" +msgstr "Επιλογή όλων" + +#: gtk_ardour/redirect_box.cc:381 +#, fuzzy +msgid "Deselect all" +msgstr "Επιλογή όλων" + +#: gtk_ardour/redirect_box.cc:389 +#, fuzzy +msgid "Inserts" +msgstr "ΑντιστÏοφή" + +#: gtk_ardour/redirect_box.cc:390 +#, fuzzy +msgid "Sends" +msgstr "ΔευτεÏόλεπτα" + +#: gtk_ardour/redirect_box.cc:393 +msgid "Select all ..." +msgstr "Επιλογή όλων ..." + +#: gtk_ardour/redirect_box.cc:406 +msgid "Activate All" +msgstr "ΕνεÏγοποίηση όλων" + +#: gtk_ardour/redirect_box.cc:407 +msgid "Deactivate All" +msgstr "ΑπενεÏγοποίηση όλων" + +#: gtk_ardour/redirect_box.cc:488 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point, there are\n" +"%3 active signal streams.\n" +"\n" +"This makes no sense - you are throwing away\n" +"part of the signal." +msgstr "" +"ΑποπειÏαθήκατε να Ï€Ïοσθέσετε ένα plug-in (%1).\n" +"Το plugin έχει %2 inputs\n" +"αλλά στο σημείο υποδοχής, υπάÏχουν\n" +"%3 ενεÏγά σήματα.\n" +"\n" +"Δεν έχει νόημα - έτσι χαÏαμίζετε\n" +"μέÏος του σήματος." + +#: gtk_ardour/redirect_box.cc:500 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point there are\n" +"only %3 active signal streams.\n" +"\n" +"This makes no sense - unless the plugin supports\n" +"side-chain inputs. A future version of Ardour will\n" +"support this type of configuration." +msgstr "" +"ΑποπειÏαθήκατε να Ï€Ïοσθέσετε ένα plug-in (%1).\n" +"Το plugin έχει %2 inputs\n" +"αλλά στο σημείο υποδοχής, υπάÏχουν\n" +"μόνο %3 ενεÏγά σήματα..\n" +"\n" +"Δεν έχει νόημα - εκτός αν το plug-in υποστηÏίζει\n" +"επι μέÏους inputs. Μελλοντική έκδοση του Ardour θα\n" +"υποστηÏίζει αυτον τον Ï„Ïπο διατάξεως." + +#: gtk_ardour/redirect_box.cc:513 +msgid "" +"You attempted to add a plugin (%1).\n" +"\n" +"The I/O configuration doesn't make sense:\n" +"\n" +"The plugin has %2 inputs and %3 outputs.\n" +"The track/bus has %4 inputs and %5 outputs.\n" +"The insertion point, has %6 active signals.\n" +"\n" +"Ardour does not understand what to do in such situations.\n" +msgstr "" +"ΑποπειÏαθήκατε να Ï€Ïοσθέσετε ένα plug-in (%1).\n" +"\n" +"Η I/O διάταξη δεν έχει νόημα:\n" +"\n" +"Το plugin έχει %2 inputs και %3 outputs.\n" +"Το κανάλι/δίαυλος έχει %4 inputs και %5 outputs.\n" +"Το σημείο υποδοχής, έχει %6 ενεÏγά σήματα.\n" +"\n" +"Ο Ardour δεν γνωÏίζει τι να κάνει σε τέτοιες πεÏιπτώσεις.\n" + +#: gtk_ardour/redirect_box.cc:616 +msgid "Pre-fader inserts, sends & plugins:" +msgstr "Pre-fader εισαγωγές, sends & plugins:" + +#: gtk_ardour/redirect_box.cc:619 +msgid "Post-fader inserts, sends & plugins:" +msgstr "Post-fader εισαγωγές, sends & plugins:" + +#: gtk_ardour/redirect_box.cc:781 +msgid "" +"You cannot reorder this set of redirects\n" +"in that way because the inputs and\n" +"outputs do not work correctly." +msgstr "" + +#: gtk_ardour/redirect_box.cc:903 +msgid "ardour: rename redirect" +msgstr "ardour: μετονομασία redirect" + +#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043 +msgid "" +"Copying the set of redirects on the clipboard failed,\n" +"probably because the I/O configuration of the plugins\n" +"could not match the configuration of this track." +msgstr "" + +#: gtk_ardour/redirect_box.cc:1064 +msgid "" +"Do you really want to remove all redirects from this track?\n" +"(this cannot be undone)" +msgstr "" +"Στ'αλήθεια θέλετε να απαλοίψετε όλα τα redirects από το κανάλι?\n" +"(δεν μποÏεί να ανακληθεί)" + +#: gtk_ardour/redirect_box.cc:1067 +msgid "" +"Do you really want to remove all redirects from this bus?\n" +"(this cannot be undone)" +msgstr "" +"Στ'αλήθεια θέλετε να απαλοίψετε όλα τα redirects από το δίαυλο?\n" +"(δεν μποÏεί να ανακληθεί)" + +#: gtk_ardour/redirect_box.cc:1071 +msgid "Yes, remove them all" +msgstr "Îαι, απάλοιψέ τα όλα" + +#: gtk_ardour/redirect_box.cc:1114 +msgid "ardour: %1" +msgstr "ardour: %1" + +#: gtk_ardour/redirect_box.cc:1156 +#, fuzzy +msgid "ardour: %1: %2 (by %3)" +msgstr "ardour: %1: %2" + +#: gtk_ardour/region_editor.cc:43 +msgid "NAME:" +msgstr "ÎŒÎΟΜΑ:" + +#: gtk_ardour/region_editor.cc:44 +msgid "lock" +msgstr "κλείδωμα" + +#: gtk_ardour/region_editor.cc:46 +msgid "opaque" +msgstr "αδιαφανής" + +#: gtk_ardour/region_editor.cc:49 +msgid "Layer" +msgstr "ΣτÏώμα" + +#: gtk_ardour/region_editor.cc:57 +msgid "ENVELOPE" +msgstr "ΧΡΟÎΟΔΙΑΓΡΑΜΜΑ" + +#: gtk_ardour/region_editor.cc:108 +msgid "mute this region" +msgstr "σιγή παÏοÏσας πεÏιοχής" + +#: gtk_ardour/region_editor.cc:109 +msgid "regions underneath this one cannot be heard" +msgstr "πεÏιοχές κάτωθι της παÏοÏσας δεν μποÏοÏν να ακουστοÏν" + +#: gtk_ardour/region_editor.cc:110 +msgid "prevent any changes to this region" +msgstr "αποτÏοπή αλλαγών σε αυτή την πεÏιοχή" + +#: gtk_ardour/region_editor.cc:111 +msgid "use the gain envelope during playback" +msgstr "χÏήση χÏονοδιαγÏάμματος του gain κατά την αναπαÏ/γή" + +#: gtk_ardour/region_editor.cc:112 +msgid "show the gain envelope" +msgstr "ανάδειξη χÏονοδιαγÏάμματος του gain" + +#: gtk_ardour/region_editor.cc:113 +msgid "use fade in curve during playback" +msgstr "χÏήση της καμπÏλης fade in κατά την αναπαÏ/γή" + +#: gtk_ardour/region_editor.cc:114 +msgid "use fade out curve during playback" +msgstr "χÏήση της καμπÏλης fade out κατά την αναπαÏ/γή" + +#: gtk_ardour/region_editor.cc:115 +msgid "audition this region" +msgstr "ακÏόαση της πεÏιοχής" + +#: gtk_ardour/region_editor.cc:148 +msgid "START:" +msgstr "ΑΡΧΗ:" + +#: gtk_ardour/region_editor.cc:150 +msgid "END:" +msgstr "ΛΗΞΗ:" + +#: gtk_ardour/region_editor.cc:152 +msgid "LENGTH:" +msgstr "ΜΗΚΟΣ:" + +#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198 +#: gtk_ardour/region_editor.cc:234 +msgid "active" +msgstr "ενεÏγό" + +#: gtk_ardour/region_editor.cc:179 +msgid "visible" +msgstr "οÏατό" + +#: gtk_ardour/region_editor.cc:197 +msgid "FADE IN" +msgstr "FADE IN" + +#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235 +msgid "msecs" +msgstr "msecs" + +#: gtk_ardour/region_editor.cc:233 +msgid "FADE OUT" +msgstr "FADE OUT" + +#: gtk_ardour/region_editor.cc:276 +msgid "ardour: region " +msgstr "ardour: πεÏιοχή " + +#: gtk_ardour/region_editor.cc:410 +msgid "fade in edit" +msgstr "επεξεÏ/σία fade in" + +#: gtk_ardour/region_editor.cc:422 +msgid "fade out edit" +msgstr "επεξεÏ/σία fade out" + +#: gtk_ardour/regionview.cc:1169 +#, fuzzy +msgid "add gain control point" +msgstr "απαλοιφή σημείου ελέγχου" + +#: gtk_ardour/route_params_ui.cc:58 +msgid "Tracks/Buses" +msgstr "κανάλια/δίαυλοι" + +#: gtk_ardour/route_params_ui.cc:59 +msgid "Pre Redirects" +msgstr "ΠÏο-Redirects" + +#: gtk_ardour/route_params_ui.cc:60 +msgid "Post Redirects" +msgstr "Μετα-Redirects" + +#: gtk_ardour/route_params_ui.cc:105 +#, fuzzy +msgid "Pre-fader Redirects" +msgstr "ΠÏο-Redirects" + +#: gtk_ardour/route_params_ui.cc:106 +#, fuzzy +msgid "Post-fader Redirects" +msgstr "Μετα-Redirects" + +#: gtk_ardour/route_params_ui.cc:138 +#, fuzzy +msgid "ardour: track/bus inspector" +msgstr "ardour: Εισαγωγή καναλιοÏ/διαÏλου" + +#: gtk_ardour/route_params_ui.cc:139 +msgid "ardour_route_parameters" +msgstr "ardour_παÏάμετÏοι_διαδÏομών" + +#: gtk_ardour/route_params_ui.cc:189 +msgid "route display list item for renamed route not found!" +msgstr "Η λίστα ανάδειξης διαδÏομών για μετονομασμένη διαδÏομή δεν ευÏέθη!" + +#: gtk_ardour/route_params_ui.cc:448 +msgid "NO TRACK" +msgstr "Κανένα κανάλι" + +#: gtk_ardour/route_params_ui.cc:669 +#, fuzzy +msgid "ardour: track/bus inspector: " +msgstr "ardour: Εισαγωγή καναλιοÏ/διαÏλου" + +#: gtk_ardour/route_params_ui.cc:673 +msgid "No Route Selected" +msgstr "Δεν επελέχθη διαδÏομή" + +#: gtk_ardour/route_params_ui.cc:674 +#, fuzzy +msgid "ardour: track/bus/inspector: no route selected" +msgstr "ardour: παÏάμετÏοι διαδÏομών: δεν επελέχθη διαδÏομή" + +#: gtk_ardour/route_ui.cc:134 +msgid "mute change" +msgstr "αλλαγή σιγής" + +#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220 +msgid "solo change" +msgstr "αλλαγή σόλο" + +#: gtk_ardour/route_ui.cc:284 +msgid "rec-enable change" +msgstr "αλλαγή rec-enable" + +#: gtk_ardour/route_ui.cc:423 +#, fuzzy +msgid "Solo-safe" +msgstr "Σόλο" + +#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474 +#, fuzzy +msgid "MIDI Bind" +msgstr "MIDI" + +#: gtk_ardour/route_ui.cc:445 +msgid "Pre Fader" +msgstr "ΠÏο Fader" + +#: gtk_ardour/route_ui.cc:452 +msgid "Post Fader" +msgstr "Μετά Fader" + +#: gtk_ardour/route_ui.cc:459 +msgid "Control Outs" +msgstr "Control Outs" + +#: gtk_ardour/route_ui.cc:466 +msgid "Main Outs" +msgstr "Main Outs" + +#: gtk_ardour/route_ui.cc:503 +msgid "mix group solo change" +msgstr "αλλαγή solo ομάδας μίξεως" + +#: gtk_ardour/route_ui.cc:537 +msgid "mix group mute change" +msgstr "αλλαγή mute ομάδας μίξεως" + +#: gtk_ardour/route_ui.cc:553 +msgid "mix group rec-enable change" +msgstr "αλλαγή rec-enable ομάδας μίξεως" + +#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258 +msgid "ardour: color selection" +msgstr "ardour: επιλογή χÏωμάτων" + +#: gtk_ardour/route_ui.cc:652 +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"You may also lose the playlist used by this track.\n" +"(cannot be undone)" +msgstr "" +"Στ'αλήθεια θέλετε να απαλοίψετε το κανάλι \"%1\" ?\n" +"Πιθανόν να χάσετε και τη λίστα που χÏησιμοποιείται από το κανάλι.\n" +"(δεν μποÏεί να ανακληθεί)" + +#: gtk_ardour/route_ui.cc:654 +msgid "" +"Do you really want to remove bus \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Στ'αλήθεια θέλετε να απαλοίψετε το κανάλι \"%1\" ?\n" +"(δεν μποÏεί να ανακληθεί)" + +#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299 +msgid "Yes, remove it." +msgstr "Îαι, απάλοιψε το." + +#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358 +msgid "new name: " +msgstr "νέο όνομα: " + +#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31 +msgid "Beats per minute" +msgstr "ΚτÏποι ανά λεπτό" + +#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35 +#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163 +msgid "Beat" +msgstr "ΚτÏπος" + +#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158 +msgid "Meter denominator" +msgstr "ΠαÏονομαστής ΜέτÏου" + +#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159 +msgid "Beats per bar" +msgstr "ΚτÏποι ανά μπάÏα" + +#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189 +msgid "whole (1)" +msgstr "ολόκληÏο (1)" + +#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191 +msgid "second (2)" +msgstr "δεÏτεÏο (2)" + +#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193 +msgid "third (3)" +msgstr "Ï„Ïίτο (3)" + +#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195 +#: gtk_ardour/tempo_dialog.cc:203 +msgid "quarter (4)" +msgstr "τέταÏτο (4)" + +#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197 +msgid "eighth (8)" +msgstr "όγδοο (8)" + +#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199 +msgid "sixteenth (16)" +msgstr "δέκατο έκτο (16)" + +#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201 +msgid "thirty-second (32)" +msgstr "Ï„Ïιακοστό-όγδοο (32)" + +#: gtk_ardour/tempo_dialog.cc:301 +msgid "garbaged note type entry (%1)" +msgstr "είσοδος(type entry) άχÏηστης σημειώσεως (%1)" + +#: gtk_ardour/tempo_dialog.cc:311 +msgid "incomprehensible note type entry (%1)" +msgstr "είσοδος(type entry) ακατανόητης σημειώσεως (%1)" + +#: gtk_ardour/time_axis_view.cc:95 +msgid "gTortnam" +msgstr "gTortnam" + +#: gtk_ardour/time_axis_view.cc:446 +msgid "Largest" +msgstr "Μέγιστο" + +#: gtk_ardour/time_axis_view.cc:447 +msgid "Large" +msgstr "Μεγάλο" + +#: gtk_ardour/time_axis_view.cc:448 +msgid "Larger" +msgstr "ΜεγαλÏτεÏο" + +#: gtk_ardour/time_axis_view.cc:450 +msgid "Smaller" +msgstr "ΜικÏότεÏο" + +#: gtk_ardour/time_axis_view.cc:451 +msgid "Small" +msgstr "ΜικÏÏŒ" + +#: gtk_ardour/time_axis_view.cc:785 +msgid "unknown track height name \"%1\" in XML GUI information" +msgstr "Άγνωστο όνομα Ïψους καναλιοÏ\"%1\" στις XML GUI πληÏοφοÏίες" + +#: gtk_ardour/time_axis_view_item.cc:69 +msgid "TimeAxisViewItemName" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:258 +msgid "new duration %1 frames is out of bounds for %2" +msgstr "νέα διάÏκεια %1 καÏέ είναι εκτός οÏίων για %2" + +#: gtk_ardour/time_selection.cc:40 +msgid "programming error: request for non-existent audio range (%1)!" +msgstr "Σφάλμα Ï€ÏογÏαμματισμοÏ: request για μη-υπάÏχον ηχητικό διάστημα (%1)!" + +#: gtk_ardour/utils.cc:57 +msgid "" +"\"\n" +"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+=" +msgstr "" +"\"\n" +"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+=" + +#: gtk_ardour/utils.cc:66 +msgid "aeiou" +msgstr "aeiou" + +#: gtk_ardour/utils.cc:75 +msgid "AEIOU" +msgstr "AEIOU" + +#: gtk_ardour/utils.cc:84 +msgid "bcdfghjklmnpqrtvwxyz" +msgstr "bcdfghjklmnpqrtvwxyz" + +#: gtk_ardour/utils.cc:93 +msgid "BCDFGHJKLMNPQRTVWXYZ" +msgstr "BCDFGHJKLMNPQRTVWXYZ" + +#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265 +msgid "bad XPM header %1" +msgstr "εσφαλμένος XPM header %1" + +#: gtk_ardour/utils.cc:516 +msgid "missing RGBA style for \"%1\"" +msgstr "" + +#: gtk_ardour/visual_time_axis.cc:297 +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Στ'αλήθεια θέλετε να απαλοίψετε το κανάλι \"%1\" ?\n" +"(δεν μποÏεί να ανακληθεί)" + +#: gtk_ardour/visual_time_axis.cc:385 +msgid "A track already exists with that name" +msgstr "Κανάλι με αυτό το όνομα ήδη υπάÏχει" + +#~ msgid "Seamless Looping" +#~ msgstr "Αδιάσπαστο Looping" + +#, fuzzy +#~ msgid "Align recorded material with:" +#~ msgstr "Στοίχιση ληφθέντος Ï…Î»Î¹ÎºÎ¿Ï Î¼Îµ" + +#~ msgid "Export to CD" +#~ msgstr "Εξαγωγή σε CD" + +#~ msgid "programming error: location/marker map does not contain location!" +#~ msgstr "" +#~ "Σφάλμα Ï€ÏογÏαμματισμοÏ: ο χάÏτης τοποθεσίας/στίγματος δεν πεÏιέχει " +#~ "τοποθεσίες!" + +#~ msgid "No toggle button pixmaps found to match toggle-button-[0-9]*.xpm$" +#~ msgstr "" +#~ "Δεν ευÏέθησαν 'toggle button pixmaps' να ταιÏιάζουν στα toggle-button-[0-" +#~ "9]*.xpm$" + +#~ msgid "" +#~ "No small push button pixmaps found to match small-round-button-[0-9]*.xpm$" +#~ msgstr "" +#~ "Δεν ευÏέθησαν 'small push button pixmaps' να ταιÏιάζουν στα small-round-" +#~ "button-[0-9]*.xpm$" + +#~ msgid "No pixmaps found to match hslider[0-9]*.xpm$" +#~ msgstr "Δεν ευÏέθησαν 'pixmaps' να ταιÏιάζουν στα hslider[0-9]*.xpm$" + +#~ msgid "No pixmaps found to match vslider[0-9]*.xpm$" +#~ msgstr "Δεν ευÏέθησαν 'pixmaps' να ταιÏιάζουν vslider[0-9]*.xpm$" + +#~ msgid "Trace MIDI Input" +#~ msgstr "Αναζήτηση MIDI Input" + +#~ msgid "Trace MIDI Output" +#~ msgstr "Αναζήτηση MIDI Output" + +#~ msgid "30 FPS non-drop" +#~ msgstr "30 FPS non-drop" + +#~ msgid "MTC Port" +#~ msgstr "MTC ΘÏÏα" + +#~ msgid "attempt to timestretch a non-audio track!" +#~ msgstr "απόπειÏα να χÏονοκαμφθεί ένα μη-ηχητικό κανάλι!" + +#~ msgid "cannot create timestretch thread - operation not carried out" +#~ msgstr "" +#~ "δεν δημιουÏγήθηκε σÏνδεσμος ΧÏονοκάμψης - η εÏγασία δεν ολοκληÏώθηκε" + +#, fuzzy +#~ msgid "move region(s) between tracks" +#~ msgstr "μετακίνηση πεÏιοχής Î¼ÎµÏ„Î±Î¾Ï ÎºÎ±Î½Î±Î»Î¹ÏŽÎ½" + +#, fuzzy +#~ msgid "copy region(s) between tracks" +#~ msgstr "αντιγÏαφή πεÏιοχής Î¼ÎµÏ„Î±Î¾Ï ÎºÎ±Î½Î±Î»Î¹ÏŽÎ½" + +#~ msgid "ardour: tempo editor" +#~ msgstr "ardour: επεξεÏγαστής χÏόνου" + +#~ msgid "mouse brush" +#~ msgstr "βοÏÏτσα ποντικιοÏ" + +#~ msgid "ardour_add_track_bus" +#~ msgstr "ardour_εισαγωγή_καναλιοÏ_διαÏλου" + +#~ msgid "ok" +#~ msgstr "Εν τάξει" + +#~ msgid "apply" +#~ msgstr "ενεÏγοποίηση" + +#~ msgid "fade" +#~ msgstr "fade" + +#~ msgid "Edit left" +#~ msgstr "ΕπεξεÏγασία αÏιστεÏοÏ" + +#~ msgid "Edit right" +#~ msgstr "ΕπεξεÏγασία δεξιοÏ" + +#~ msgid "Edit fade" +#~ msgstr "ΕπεξεÏγασία fade" + +#~ msgid "Export region" +#~ msgstr "Εξαγωγή πεÏιοχής" + +#~ msgid "Bounce region" +#~ msgstr "Αναπήδηση πεÏιοχής" + +#~ msgid "Region" +#~ msgstr "ΠεÏιοχή" + +#~ msgid "Play selected region" +#~ msgstr "ΑναπαÏ/γή επιλεγμένης ΠεÏιοχής" + +#~ msgid "clear connections" +#~ msgstr "εκκαθάÏιση συνδέσεων" + +#~ msgid "add comments/notes here" +#~ msgstr "Ï€Ïόσθεση σχολίων/σημειώσεων εδώ" + +#~ msgid "Crossfades in use" +#~ msgstr "Crossfades εν ενεÏγεία" + +#, fuzzy +#~ msgid "outside this computer" +#~ msgstr "ΑπόκÏυψη παÏόντος καναλιοÏ" + +#, fuzzy +#~ msgid "inside this computer" +#~ msgstr "ΑπόκÏυψη παÏόντος καναλιοÏ" + +#~ msgid "track %1 has no input connections [This Message To Be Expanded]" +#~ msgstr "Το κανάλι %1 δεν εχει συνδέσεις λήψεως[Μήνυμα Ï€Ïος επέκταση]" + +#~ msgid "SR: %u kHz" +#~ msgstr "SR: %u kHz" + +#~ msgid "Export CD track markers" +#~ msgstr "Εξαγωγή σε CD από μαÏκάÏισμα καναλιοÏ" + +#~ msgid "Route Parameters" +#~ msgstr "ΠαÏάμετÏοι διαδÏομών" + +#~ msgid "Use Other" +#~ msgstr "ΧÏησιμοποίηση άλλου" + +#~ msgid "zoom to frame" +#~ msgstr "zoom σε καÏέ" + +#~ msgid "Display Automatic Regions" +#~ msgstr "Ανάδειξη Αυτομάτων ΠεÏιοχών" + +#~ msgid "Edit tempo" +#~ msgstr "Επεξ/σία ΧÏόνου" + +#~ msgid "Ardour is done. Come again. Have a nice day. Etc.\n" +#~ msgstr "Ο Ardour τελείωσε. Îα μας ξανάÏθετε. Καλή ημέÏα να έχετε. Κλπ.\n" + +#~ msgid "External MIDI Control" +#~ msgstr "ΕξωτεÏικός Έλεγχος MIDI" + +#~ msgid " -U, --ui-rcfile path Use a specific UI style file\n" +#~ msgstr "" +#~ " -U, --ui-rcfile path ΧÏήση συγκεκÏιμένου αÏχείου για UI " +#~ "στυλ\n" + +#~ msgid "INPUTs" +#~ msgstr "Είσοδος(οι)" + +#~ msgid "OUTPUTs" +#~ msgstr "'Εξοδος(οι)" + +#~ msgid "ardour: route parameters" +#~ msgstr "ardour: παÏάμετÏοι διαδÏομών" + +#~ msgid "ardour: route parameters: " +#~ msgstr "ardour: παÏάμετÏοι διαδÏομών: " diff --git a/gtk2_ardour/po/es_ES.po b/gtk2_ardour/po/es_ES.po new file mode 100644 index 0000000000..6b1c962f51 --- /dev/null +++ b/gtk2_ardour/po/es_ES.po @@ -0,0 +1,5194 @@ +# Ardour Spanish translation file +# Copyright (C) 2003-2004 Paul Davis +# This file is distributed under the same license as the Ardour package. +# Author: Alex Krohn +# +msgid "" +msgstr "" +"Project-Id-Version: ardour 0.688.4\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2005-09-19 18:09-0400\n" +"PO-Revision-Date: 2004-01-21 12:45+0100\n" +"Last-Translator: Alex Krohn \n" +"Language-Team: Spanish\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: gtk_ardour/about.cc:134 +msgid "Marcus Andersson" +msgstr "" + +#: gtk_ardour/about.cc:135 +msgid "Jeremy Hall" +msgstr "" + +#: gtk_ardour/about.cc:136 +msgid "Steve Harris" +msgstr "" + +#: gtk_ardour/about.cc:137 +msgid "Tim Mayberry" +msgstr "" + +#: gtk_ardour/about.cc:138 +msgid "Mark Stewart" +msgstr "" + +#: gtk_ardour/about.cc:139 +msgid "Sam Chessman" +msgstr "" + +#: gtk_ardour/about.cc:140 +msgid "Jack O'Quin" +msgstr "" + +#: gtk_ardour/about.cc:141 +msgid "Matt Krai" +msgstr "" + +#: gtk_ardour/about.cc:142 +msgid "Ben Bell" +msgstr "" + +#: gtk_ardour/about.cc:143 +msgid "Gerard van Dongen" +msgstr "" + +#: gtk_ardour/about.cc:144 +msgid "Thomas Charbonnel" +msgstr "" + +#: gtk_ardour/about.cc:145 +msgid "Nick Mainsbridge" +msgstr "" + +#: gtk_ardour/about.cc:146 +msgid "Colin Law" +msgstr "" + +#: gtk_ardour/about.cc:147 +msgid "Sampo Savolainen" +msgstr "" + +#: gtk_ardour/about.cc:148 +msgid "Joshua Leach" +msgstr "" + +#: gtk_ardour/about.cc:149 +msgid "Rob Holland" +msgstr "" + +#: gtk_ardour/about.cc:150 +msgid "Per Sigmond" +msgstr "" + +#: gtk_ardour/about.cc:151 +msgid "Doug Mclain" +msgstr "" + +#: gtk_ardour/about.cc:156 +msgid "" +"French:\n" +"\tAlain Fréhel " +msgstr "" + +#: gtk_ardour/about.cc:157 +msgid "" +"German:\n" +"\tKarsten Petersen " +msgstr "" + +#: gtk_ardour/about.cc:158 +msgid "" +"Italian:\n" +"\tFilippo Pappalardo " +msgstr "" + +#: gtk_ardour/about.cc:159 +msgid "" +"Portuguese:\n" +"\tRui Nuno Capela " +msgstr "" + +#: gtk_ardour/about.cc:160 +msgid "" +"Brazilian Portuguese:\n" +"\tAlexander da Franca Fernandes \n" +"\tChris Ross " +msgstr "" + +#: gtk_ardour/about.cc:162 +msgid "" +"Spanish:\n" +"\t Alex Krohn " +msgstr "" + +#: gtk_ardour/about.cc:163 +msgid "" +"Russian:\n" +"\t Igor Blinov " +msgstr "" + +#: gtk_ardour/about.cc:181 +#, fuzzy +msgid "" +"Copyright (C) 1999-2005 Paul Davis\n" +"Ardour comes with ABSOLUTELY NO WARRANTY\n" +"This is free software, and you are welcome to redistribute it\n" +"under certain conditions; see the file COPYING for details.\n" +msgstr "" +"Ardour no provee ningun tipo de garant�\n" +"Este software es gratuito y usted lo puede redistribuir\n" +"bajo ciertas condiciones;lea el archivo COPYING(en ingl�)\n" +"para m� detalles\n" + +#: gtk_ardour/about.cc:188 +msgid "" +"Ardour: %1\n" +"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)" +msgstr "" + +#: gtk_ardour/about.cc:206 +msgid "" +"Primary author:\n" +"\tPaul Davis\n" +"\n" +"Major developers:\n" +"\tJesse Chappell\n" +"\tTaybin Rutkin\n" +"Contributors:\n" +"\t" +msgstr "" + +#: gtk_ardour/about.cc:243 +msgid "Authors" +msgstr "Autores" + +#: gtk_ardour/about.cc:244 +#, fuzzy +msgid "Translators" +msgstr "Traductores" + +#: gtk_ardour/about.cc:361 +msgid "cannot open splash image file \"%1\"" +msgstr "no se pudo mostrar el la imagen Acerca de \"%1\"" + +#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33 +#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81 +#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977 +#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85 +#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777 +#: gtk_ardour/redirect_box.cc:900 +msgid "OK" +msgstr "OK" + +#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92 +#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046 +#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72 +#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982 +#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733 +#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000 +#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129 +#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785 +#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86 +#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072 +#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33 +#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161 +msgid "Cancel" +msgstr "Cancelar" + +#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94 +msgid "Tracks" +msgstr "Pistas" + +#: gtk_ardour/add_route_dialog.cc:43 +msgid "Busses" +msgstr "Buses" + +#: gtk_ardour/add_route_dialog.cc:48 +msgid "ardour: add track/bus" +msgstr "ardour: agregar Pistas/bus" + +#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81 +msgid "Add" +msgstr "Agregar" + +#: gtk_ardour/add_route_dialog.cc:86 +msgid "Name (template)" +msgstr "Nombre (esquema)" + +#: gtk_ardour/ardour_ui.cc:798 +msgid "" +"pre\n" +"roll" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:799 +msgid "" +"post\n" +"roll" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:807 +msgid "% " +msgstr "" + +#: gtk_ardour/ardour_ui.cc:808 +msgid "spring" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:810 +msgid "" +"punch\n" +"in" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:811 +msgid "" +"punch\n" +"out" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:812 +msgid "" +"auto\n" +"return" +msgstr "" +"retorno\n" +"autom�ico" + +#: gtk_ardour/ardour_ui.cc:813 +msgid "" +"auto\n" +"play" +msgstr "" +"reproduccn\n" +"autom�ica" + +#: gtk_ardour/ardour_ui.cc:814 +msgid "" +"auto\n" +"input" +msgstr "" +"auto\n" +"monitoreo" + +#: gtk_ardour/ardour_ui.cc:815 +msgid "click" +msgstr "metrnomo" + +#: gtk_ardour/ardour_ui.cc:816 +msgid "" +"follow\n" +"PH" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:817 +msgid "AUDITIONING" +msgstr "AUDITANDO" + +#: gtk_ardour/ardour_ui.cc:818 +msgid "SOLO" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:870 +#, fuzzy +msgid "Percentage" +msgstr "Porcentage" + +#: gtk_ardour/ardour_ui.cc:872 +#, fuzzy +msgid "Semitones" +msgstr "Semitonos" + +#: gtk_ardour/ardour_ui.cc:875 +#, fuzzy +msgid "Sprung" +msgstr "Salto" + +#: gtk_ardour/ardour_ui.cc:877 +msgid "Wheel" +msgstr "Rueda" + +#: gtk_ardour/ardour_ui.cc:902 +msgid "" +"You cannot record-enable\n" +"track %1\n" +"because it has no input connections.\n" +"You would be wasting space recording silence." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1073 +msgid "quit" +msgstr "salir" + +#: gtk_ardour/ardour_ui.cc:1082 +msgid "" +"Ardour was unable to save your session.\n" +"\n" +"If you still wish to quit, please use the\n" +"\n" +"\"Just quit\" option." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1107 +msgid "Save and %1" +msgstr "Guardar y %1" + +#: gtk_ardour/ardour_ui.cc:1112 +msgid "Just %1" +msgstr "Slo %1" + +#: gtk_ardour/ardour_ui.cc:1117 +msgid "Don't %1" +msgstr "No %1" + +#: gtk_ardour/ardour_ui.cc:1126 +#, fuzzy +msgid "session" +msgstr "Sesin" + +#: gtk_ardour/ardour_ui.cc:1128 +#, fuzzy +msgid "snapshot" +msgstr "Capturar instant�ea de sesin" + +#: gtk_ardour/ardour_ui.cc:1130 +#, fuzzy +msgid "" +"The %1\n" +"\"%2\"\n" +"has not been saved.\n" +"\n" +"Any changes made this time\n" +"will be lost unless you save it.\n" +"\n" +"What do you want to do?" +msgstr "" +"No ha guardado \"%1\"\n" +"la sesin actual.\n" +"\n" +"Cualquier cambio que haya hecho\n" +"se perder�si no selecciona guardar sesin.\n" +"\n" +"Qu�desea hacer?" + +#: gtk_ardour/ardour_ui.cc:1151 +msgid "Prompter" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1152 +msgid "ardour: save session?" +msgstr "ardour: guardar sesin?" + +#: gtk_ardour/ardour_ui.cc:1219 +#, fuzzy, c-format +msgid "disconnected" +msgstr "Desconectar" + +#: gtk_ardour/ardour_ui.cc:1226 +#, fuzzy, c-format +msgid "SR: %.1f kHz / %4.1f msecs" +msgstr "SR: %.1f kHz" + +#: gtk_ardour/ardour_ui.cc:1230 +#, c-format +msgid "SR: %u kHz / %4.1f msecs" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1243 +#, fuzzy, c-format +msgid "DSP Load: %.1f%%" +msgstr "CPU usada: %.1f%%" + +#: gtk_ardour/ardour_ui.cc:1253 +#, c-format +msgid "Disk r:%5.1f w:%5.1f MB/s" +msgstr "Disco r:%5.1f w:%5.1f MB/s" + +#: gtk_ardour/ardour_ui.cc:1267 +#, fuzzy, c-format +msgid "Buffers p:%%% c:%%%" +msgstr "Buffers p:%5.0f%% c:%5.0f%%" + +#: gtk_ardour/ardour_ui.cc:1294 +msgid "space: 24hrs+" +msgstr "disponible: 24hrs+" + +#: gtk_ardour/ardour_ui.cc:1324 +#, c-format +msgid "space: %02dh:%02dm:%02ds" +msgstr "disponible: %02dh:%02dm:%02ds" + +#: gtk_ardour/ardour_ui.cc:1575 +msgid "programming error: impossible control method" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1800 +msgid "cancel" +msgstr "cancelar" + +#: gtk_ardour/ardour_ui.cc:1801 +msgid "rescan" +msgstr "buscar de nuevo" + +# +#: gtk_ardour/ardour_ui.cc:1842 +msgid "open session" +msgstr "Abrir sesin" + +#: gtk_ardour/ardour_ui.cc:1897 +msgid "Patience is a virtue.\n" +msgstr "La paciencia es una virtud.\n" + +#: gtk_ardour/ardour_ui.cc:1906 +msgid "You cannot add a track without a session already loaded." +msgstr "No puede agregar pistas hasta que haya creado o abierto una sesin." + +#: gtk_ardour/ardour_ui.cc:1913 +msgid "could not create new audio track" +msgstr "no se pudo crear la nueva pista" + +#: gtk_ardour/ardour_ui.cc:1917 +msgid "could not create new audio bus" +msgstr "no se pudo crear el nuevo bus" + +#: gtk_ardour/ardour_ui.cc:1936 +msgid "" +"There are insufficient JACK ports available\n" +"to create a new track or bus.\n" +"You should save Ardour, exit and\n" +"restart JACK with more ports." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2071 +msgid "" +"Please create 1 or more track\n" +"before trying to record.\n" +"Check the Session menu." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2312 +#, fuzzy +msgid "" +"JACK has either been shutdown or it\n" +"disconnected Ardour because Ardour\n" +"was not fast enough. You can save the\n" +"session and/or try to reconnect to JACK ." +msgstr "" +"El programa Jackd fue detenido o �te \n" +"desconect a Ardour por no ser \n" +"suficientemente r�ido.\n" +"Usted puede guardar su sesin ahora\n" +"sin perder los cambios hechos.Luego,reinicie a Ardour y a Jackd." + +#: gtk_ardour/ardour_ui.cc:2328 +msgid "Unable to create all required ports" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2336 +#, fuzzy +msgid "Unable to start the session running" +msgstr "Ir al inicio de la sesin" + +#: gtk_ardour/ardour_ui.cc:2472 +msgid "No Stream" +msgstr "Sin Flujo" + +#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518 +msgid "none" +msgstr "ninguno" + +#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527 +#: gtk_ardour/automation_time_axis.cc:189 +#: gtk_ardour/automation_time_axis.cc:218 +#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211 +#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947 +#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659 +msgid "off" +msgstr "off" + +#: gtk_ardour/ardour_ui.cc:2548 +msgid "Name for snapshot" +msgstr "Nombre a captura de sesin" + +#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294 +msgid "Name for mix template:" +msgstr "Nombre a esquema de mixer" + +#: gtk_ardour/ardour_ui.cc:2717 +msgid "-template" +msgstr "-esquema" + +#: gtk_ardour/ardour_ui.cc:2760 +msgid "Session %1 already exists at %2" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2832 +msgid "" +"You do not have write access to this session.\n" +"This prevents the session from being loaded." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897 +msgid "Session \"%1 (snapshot %2)\" did not load successfully" +msgstr "No se puede cargar la sesin \"%1 (captura %2)\" " + +#: gtk_ardour/ardour_ui.cc:2966 +msgid "" +"No audio files were ready for cleanup\n" +"\n" +"If this seems suprising, check for any existing\n" +"snapshots. These may still include regions that\n" +"require some unused files to continue to exist." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001 +msgid "files" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003 +msgid "file" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3026 +msgid "ardour: cleanup" +msgstr "ardour: limpiar" + +#: gtk_ardour/ardour_ui.cc:3040 +msgid "" +"Cleanup is a destructive operation.\n" +"ALL undo/redo information will be lost if you cleanup.\n" +"Unused audio files will be moved to a \"dead sounds\" location." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3045 +msgid "Proceed with cleanup" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3061 +#, fuzzy +msgid "CleanupDialog" +msgstr "Limpiar" + +#: gtk_ardour/ardour_ui.cc:3062 +#, fuzzy +msgid "ardour cleanup" +msgstr "ardour: limpiar" + +#: gtk_ardour/ardour_ui.cc:3063 +#, fuzzy +msgid "ardour_cleanup" +msgstr "ardour: limpiar" + +#: gtk_ardour/ardour_ui.cc:3086 +msgid "cleaned files" +msgstr "archivos limpios" + +#: gtk_ardour/ardour_ui.cc:3087 +#, fuzzy +msgid "" +"The following %1 %2 were not in use.\n" +"The next time you flush the wastebasket\n" +"it will release an additional %3 %4bytes\n" +"of disk space" +msgstr "" +"Los siguientes %1 archivos no estaban en uso \n" +"Cuando vuelva a vaciar la papelera\n" +"se liberar�%2 megabytes de espacio en disco \n" + +#: gtk_ardour/ardour_ui.cc:3110 +#, fuzzy +msgid "deleted file" +msgstr "archivos eliminados" + +#: gtk_ardour/ardour_ui.cc:3111 +#, fuzzy +msgid "" +"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space" +msgstr "" +"Los siguientes %1 archivos fueron eliminados, liberando %2 megabytes de " +"espacio" + +#: gtk_ardour/ardour_ui.cc:3226 +msgid "Recording was stopped because your system could not keep up." +msgstr "Se detuvo la grabacin porque el sistema se sobrecarg" + +#: gtk_ardour/ardour_ui.cc:3248 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to write data to disk\n" +"quickly enough to keep up with recording.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3266 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to read data from disk\n" +"quickly enough to keep up with playback.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3291 +msgid "Recover from crash" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3292 +msgid "Ignore crash data" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3293 +msgid "" +"This session appears to have been in\n" +"middle of recording when ardour or\n" +"the computer was shutdown.\n" +"\n" +"Ardour can recover any captured audio for\n" +"you, or it can ignore it. Please decide\n" +"what you would like to do.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3338 +#, fuzzy +msgid "Could not disconnect from JACK" +msgstr "No se pudo conectar a JACK con el nombre \"%1\"" + +#: gtk_ardour/ardour_ui.cc:3351 +#, fuzzy +msgid "Could not reconnect to JACK" +msgstr "No se pudo conectar a JACK con el nombre \"%1\"" + +#: gtk_ardour/ardour_ui2.cc:60 +msgid "UI: cannot setup editor" +msgstr "no se pudo iniciar el editor" + +#: gtk_ardour/ardour_ui2.cc:65 +msgid "UI: cannot setup mixer" +msgstr "no se pudo iniciar el mixer" + +#: gtk_ardour/ardour_ui2.cc:70 +msgid "UI: cannot setup meter_bridge" +msgstr "no se pudo iniciar el medidor volum�rico (VU)" + +#: gtk_ardour/ardour_ui2.cc:98 +msgid "MMC + Local" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:99 +msgid "MMC" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:100 +msgid "Local" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:117 +msgid "MMC ID" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:215 +msgid "Play from playhead" +msgstr "Reproduzir a partir del in�io" + +#: gtk_ardour/ardour_ui2.cc:216 +msgid "Stop playback" +msgstr "Detener la reproduccion" + +#: gtk_ardour/ardour_ui2.cc:217 +#, fuzzy +msgid "Play range/selection" +msgstr "Reproducir seleccin" + +#: gtk_ardour/ardour_ui2.cc:218 +msgid "Go to start of session" +msgstr "Ir al inicio de la sesin" + +#: gtk_ardour/ardour_ui2.cc:219 +msgid "Go to end of session" +msgstr "Ir al final de la sesin" + +#: gtk_ardour/ardour_ui2.cc:220 +#, fuzzy +msgid "Play loop range" +msgstr "Reproducir el intervalo cont�uamente" + +#: gtk_ardour/ardour_ui2.cc:221 +msgid "Return to last playback start when stopped" +msgstr "Al detenerse, volver a donde inici la reproduccin" + +#: gtk_ardour/ardour_ui2.cc:222 +msgid "Start playback after any locate" +msgstr "" +"Reproducir inmedi�amente despu� de relocalizar la barra de reproduccin" + +#: gtk_ardour/ardour_ui2.cc:223 +msgid "Be sensible about input monitoring" +msgstr "Monitorizacin sensible de entradas" + +#: gtk_ardour/ardour_ui2.cc:224 +msgid "Start recording at auto-punch start" +msgstr "Iniciar grabacin en el punto auto-punch start(inicio)" + +#: gtk_ardour/ardour_ui2.cc:225 +msgid "Stop recording at auto-punch end" +msgstr "Detener grabacin en el punto auto-punch end(final)" + +#: gtk_ardour/ardour_ui2.cc:226 +msgid "Enable/Disable audio click" +msgstr "Habilitar/desabilitar metrnomo" + +#: gtk_ardour/ardour_ui2.cc:227 +#, fuzzy +msgid "Enable/Disable follow playhead" +msgstr "Habilitar/desbilitar reproduccin cont�ua" + +#: gtk_ardour/ardour_ui2.cc:228 +#, fuzzy +msgid "Shuttle speed control" +msgstr "Control de velocidad y sentido de reproduccin(pitch)" + +#: gtk_ardour/ardour_ui2.cc:229 +#, fuzzy, c-format +msgid "Select semitones or %%-age for speed display" +msgstr "Mostrar velocidad en semitonos o %-age" + +#: gtk_ardour/ardour_ui2.cc:230 +msgid "Select sprung or wheel behaviour" +msgstr "Modo Salto(cambio constante) o Rueda deslizante(cambio moment�eo)" + +#: gtk_ardour/ardour_ui2.cc:231 +#, fuzzy +msgid "Current transport speed" +msgstr "Velocidad actual de transporte" + +#: gtk_ardour/ardour_ui2.cc:312 +msgid "Primary clock" +msgstr "Reloj primario" + +#: gtk_ardour/ardour_ui2.cc:313 +msgid "secondary clock" +msgstr "Reloj secundario" + +#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751 +#: gtk_ardour/ardour_ui2.cc:770 +msgid "stopped" +msgstr "detenido" + +#: gtk_ardour/ardour_ui2.cc:431 +msgid "ardour: clock" +msgstr "ardour: reloj" + +#: gtk_ardour/ardour_ui2.cc:721 +msgid "st" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:731 +#, fuzzy +msgid "sprung" +msgstr "Salto" + +#: gtk_ardour/ardour_ui2.cc:742 +#, fuzzy +msgid "wheel" +msgstr "Rueda" + +#: gtk_ardour/ardour_ui_dependents.cc:74 +msgid "keyboard_target: error setting binding state: invalid node" +msgstr "" + +#: gtk_ardour/ardour_ui_dialogs.cc:158 +msgid "close session" +msgstr "cerrar sesin" + +#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895 +msgid "New" +msgstr "Nuevo" + +#: gtk_ardour/ardour_ui_ed.cc:76 +msgid "Open" +msgstr "Abrir" + +#: gtk_ardour/ardour_ui_ed.cc:77 +msgid "Recent" +msgstr "Reciente" + +#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +msgid "Close" +msgstr "Cerrar" + +#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488 +msgid "Add Track/Bus" +msgstr "Agregar Pista/Bus" + +#: gtk_ardour/ardour_ui_ed.cc:99 +msgid "Connect" +msgstr "Conectar" + +#: gtk_ardour/ardour_ui_ed.cc:100 +msgid "Image Compositor" +msgstr "Compositor de imagen" + +#: gtk_ardour/ardour_ui_ed.cc:114 +msgid "Save" +msgstr "Guardar" + +#: gtk_ardour/ardour_ui_ed.cc:118 +msgid "Snapshot" +msgstr "Capturar instant�ea de sesin" + +#: gtk_ardour/ardour_ui_ed.cc:126 +msgid "Save Template..." +msgstr "Guardar esquema" + +#: gtk_ardour/ardour_ui_ed.cc:133 +msgid "Export session to audiofile..." +msgstr "Exportar sesin a archivo de audio" + +#: gtk_ardour/ardour_ui_ed.cc:134 +#, fuzzy +msgid "Export range to audiofile..." +msgstr "Exportar sesin a archivo de audio" + +#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312 +#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118 +#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227 +msgid "Export" +msgstr "Exportar" + +#: gtk_ardour/ardour_ui_ed.cc:146 +msgid "Cleanup unused sources" +msgstr "Arrojar archivos no usados a papelera" + +#: gtk_ardour/ardour_ui_ed.cc:147 +msgid "Flush wastebasket" +msgstr "Vaciar papelera" + +#: gtk_ardour/ardour_ui_ed.cc:149 +msgid "Cleanup" +msgstr "Limpiar" + +#: gtk_ardour/ardour_ui_ed.cc:154 +msgid "Quit" +msgstr "Salir" + +#: gtk_ardour/ardour_ui_ed.cc:156 +msgid "Session" +msgstr "Sesin" + +#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287 +#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499 +#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570 +#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412 +msgid "Edit" +msgstr "Editar" + +#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572 +#: gtk_ardour/mixer_strip.cc:631 +msgid "Disconnect" +msgstr "Desconectar" + +#: gtk_ardour/ardour_ui_ed.cc:174 +#, fuzzy +msgid "Reconnect" +msgstr "Conectar" + +#: gtk_ardour/ardour_ui_ed.cc:192 +msgid "Latency" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:195 +msgid "JACK" +msgstr "JACK" + +#: gtk_ardour/ardour_ui_ed.cc:205 +msgid "Editor" +msgstr "Editor" + +#: gtk_ardour/ardour_ui_ed.cc:206 +msgid "Mixer" +msgstr "Mixer" + +#: gtk_ardour/ardour_ui_ed.cc:212 +msgid "Options Editor" +msgstr "Opciones Editor" + +#: gtk_ardour/ardour_ui_ed.cc:219 +msgid "Audio Library" +msgstr "Biblioteca de Audio" + +#: gtk_ardour/ardour_ui_ed.cc:225 +#, fuzzy +msgid "Track/Bus Inspector" +msgstr "Pistas/Buses" + +#: gtk_ardour/ardour_ui_ed.cc:232 +msgid "Connections" +msgstr "Conecciones" + +#: gtk_ardour/ardour_ui_ed.cc:240 +msgid "Meter Bridge" +msgstr "V�ETRO" + +#: gtk_ardour/ardour_ui_ed.cc:248 +msgid "Locations" +msgstr "Localizaciones" + +#: gtk_ardour/ardour_ui_ed.cc:255 +msgid "Big Clock" +msgstr "Reloj Grande" + +#: gtk_ardour/ardour_ui_ed.cc:261 +msgid "About" +msgstr "Acerca de" + +#: gtk_ardour/ardour_ui_ed.cc:264 +msgid "Windows" +msgstr "Ventanas" + +#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203 +msgid "SMPTE" +msgstr "" + +#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202 +#: gtk_ardour/editor_rulers.cc:359 +msgid "Bars:Beats" +msgstr "Compaces:Pulsos" + +#: gtk_ardour/audio_clock.cc:1642 +msgid "Minutes:Seconds" +msgstr "Minutos:Segundos" + +#: gtk_ardour/audio_clock.cc:1643 +msgid "Audio Frames" +msgstr "Cuadros de Audio" + +#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356 +#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713 +#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774 +#: gtk_ardour/option_editor.cc:794 +msgid "Off" +msgstr "Deshabilitar" + +#: gtk_ardour/audio_clock.cc:1646 +msgid "Mode" +msgstr "Modo" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523 +msgid "m" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524 +msgid "s" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:104 +msgid "r" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:108 +msgid "g" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:109 +msgid "p" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44 +#: gtk_ardour/visual_time_axis.cc:90 +msgid "h" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:111 +msgid "a" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89 +msgid "v" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:185 +msgid "Record" +msgstr "Grabar" + +#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191 +msgid "Solo" +msgstr "Solo" + +#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236 +#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433 +msgid "Mute" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:188 +msgid "Edit Group" +msgstr "Editar Grupo" + +#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110 +msgid "Display Height" +msgstr "Tamao de pista" + +#: gtk_ardour/audio_time_axis.cc:190 +msgid "Playlist" +msgstr "Lista de reproduccin" + +#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752 +msgid "Automation" +msgstr "Automatizacin" + +#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111 +msgid "Visual options" +msgstr "Opciones visuales" + +#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112 +msgid "Hide this track" +msgstr "Ocultar esta pista" + +#: gtk_ardour/audio_time_axis.cc:349 +msgid "No group" +msgstr "Sin grupo" + +#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447 +#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229 +msgid "Height" +msgstr "Altura" + +#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266 +#: gtk_ardour/marker_time_axis.cc:230 +msgid "Color" +msgstr "Color" + +#: gtk_ardour/audio_time_axis.cc:720 +msgid "Hide all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:721 +msgid "Show all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:729 +#, fuzzy +msgid "show all automation" +msgstr "Mostrar toda automatizacin" + +#: gtk_ardour/audio_time_axis.cc:732 +#, fuzzy +msgid "show existing automation" +msgstr "Mostrar toda automatizacin" + +#: gtk_ardour/audio_time_axis.cc:735 +#, fuzzy +msgid "hide all automation" +msgstr "ocultar toda automatizacin" + +#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204 +#: gtk_ardour/editor.cc:234 +msgid "gain" +msgstr "volumen" + +#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244 +msgid "pan" +msgstr "balance" + +#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388 +msgid "Plugins" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95 +msgid "Show waveforms" +msgstr "Mostrar onda de audio" + +#: gtk_ardour/audio_time_axis.cc:766 +msgid "Traditional" +msgstr "Tradicional" + +#: gtk_ardour/audio_time_axis.cc:769 +msgid "Rectified" +msgstr "Corregido" + +#: gtk_ardour/audio_time_axis.cc:772 +msgid "Waveform" +msgstr "Onda de audio" + +#: gtk_ardour/audio_time_axis.cc:782 +#, fuzzy +msgid "align with existing material" +msgstr "Material existente" + +#: gtk_ardour/audio_time_axis.cc:787 +#, fuzzy +msgid "align with capture time" +msgstr "Tiempo de captura" + +#: gtk_ardour/audio_time_axis.cc:793 +#, fuzzy +msgid "Alignment" +msgstr "Alinear" + +#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288 +msgid "Active" +msgstr "Activar" + +#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386 +#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467 +#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269 +#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233 +#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83 +msgid "Remove" +msgstr "Quitar" + +#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880 +#: gtk_ardour/audio_time_axis.cc:911 +#, fuzzy +msgid "Name for playlist" +msgstr "Nombre a captura de sesin" + +#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433 +msgid "a track already exists with that name" +msgstr "ya existe una pista con este nombre" + +#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001 +#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539 +msgid "programming error: " +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:1889 +msgid "Current: %1" +msgstr "Actual: %1" + +#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452 +#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226 +#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377 +msgid "Rename" +msgstr "Renombrar" + +#: gtk_ardour/audio_time_axis.cc:1896 +msgid "New Copy" +msgstr "Nueva Copia" + +#: gtk_ardour/audio_time_axis.cc:1898 +msgid "Clear Current" +msgstr "Borrar actual" + +#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472 +#: gtk_ardour/editor.cc:2557 +msgid "Select" +msgstr "Seleccionar" + +#: gtk_ardour/automation_line.cc:904 +#, fuzzy +msgid "automation event move" +msgstr "mover evento de automatizacin" + +#: gtk_ardour/automation_line.cc:906 +#, fuzzy +msgid "automation range drag" +msgstr "desplazar intervalo de automatizacin" + +#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64 +#, fuzzy +msgid "remove control point" +msgstr "Remover punto de sincron�" + +#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010 +msgid "clear" +msgstr "borrar" + +#: gtk_ardour/automation_time_axis.cc:80 +msgid "track height" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:81 +#, fuzzy +msgid "automation state" +msgstr "estado de automatizacin de balance" + +#: gtk_ardour/automation_time_axis.cc:82 +#, fuzzy +msgid "clear track" +msgstr "borrar intervalos" + +#: gtk_ardour/automation_time_axis.cc:83 +#, fuzzy +msgid "hide track" +msgstr "Ocultar esta pista" + +#: gtk_ardour/automation_time_axis.cc:191 +#: gtk_ardour/automation_time_axis.cc:229 +#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213 +#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419 +#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50 +msgid "play" +msgstr "reproducir" + +#: gtk_ardour/automation_time_axis.cc:193 +#: gtk_ardour/automation_time_axis.cc:240 +#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215 +#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422 +#: gtk_ardour/plugin_ui.cc:663 +msgid "write" +msgstr "escritura" + +#: gtk_ardour/automation_time_axis.cc:195 +#: gtk_ardour/automation_time_axis.cc:251 +#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217 +#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953 +#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665 +#, fuzzy +msgid "touch" +msgstr "tocar" + +#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274 +#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428 +msgid "???" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:276 +#, fuzzy +msgid "clear automation" +msgstr "borrar localizaciones" + +#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453 +#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398 +msgid "Hide" +msgstr "Ocultar" + +#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52 +#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364 +msgid "Clear" +msgstr "Quitar todos" + +#: gtk_ardour/automation_time_axis.cc:474 +#, fuzzy +msgid "State" +msgstr "Inicio" + +#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49 +msgid "Input Connections" +msgstr "Conecciones de entrada" + +#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48 +msgid "Output Connections" +msgstr "Conecciones de salida" + +#: gtk_ardour/connection_editor.cc:49 +#, fuzzy +msgid "New Input" +msgstr "nueva entrada" + +#: gtk_ardour/connection_editor.cc:50 +#, fuzzy +msgid "New Output" +msgstr "nueva salida" + +#: gtk_ardour/connection_editor.cc:51 +#, fuzzy +msgid "Delete" +msgstr "quitar" + +#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96 +#, fuzzy +msgid "Add Port" +msgstr "agregar puerto" + +#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105 +#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786 +#, fuzzy +msgid "Rescan" +msgstr "buscar de nuevo" + +#: gtk_ardour/connection_editor.cc:101 +msgid "Available Ports" +msgstr "Puertos Disponibles" + +#: gtk_ardour/connection_editor.cc:183 +msgid "ardour: connections" +msgstr "ardour: conecciones" + +#: gtk_ardour/connection_editor.cc:513 +#, c-format +msgid "in %d" +msgstr "em %d" + +#: gtk_ardour/connection_editor.cc:644 +msgid "Name for new connection:" +msgstr "Nombre para nueva coneccin:" + +#: gtk_ardour/crossfade_edit.cc:71 +#, fuzzy +msgid "crossfade editor" +msgstr "editar fade in" + +#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449 +#, fuzzy +msgid "Reset" +msgstr "resetear" + +#: gtk_ardour/crossfade_edit.cc:78 +#, fuzzy +msgid "Fade" +msgstr "Fades" + +#: gtk_ardour/crossfade_edit.cc:79 +msgid "Out (dry)" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:80 +#, fuzzy +msgid "Out" +msgstr "Salidas" + +#: gtk_ardour/crossfade_edit.cc:81 +msgid "In (dry)" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:82 +msgid "In" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:84 +msgid "With Pre-roll" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:85 +msgid "With Post-roll" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:93 +msgid "Fade In" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:94 +msgid "Fade Out" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:98 +msgid "ardour: x-fade edit" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311 +#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189 +msgid "Audition" +msgstr "Audicionando" + +#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804 +msgid "Regions/name" +msgstr "Regiones/nombre" + +#: gtk_ardour/editor.cc:108 +msgid "Chunks" +msgstr "Trechos" + +#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079 +msgid "Slide" +msgstr "Deslizar" + +#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077 +msgid "Splice" +msgstr "Reunir" + +#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136 +#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96 +#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977 +msgid "None" +msgstr "Ningn" + +#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124 +#, fuzzy +msgid "CD Frames" +msgstr "Cuadros" + +#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126 +#, fuzzy +msgid "SMPTE Frames" +msgstr "SMPTE Cuadros/segundo" + +#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128 +#, fuzzy +msgid "SMPTE Seconds" +msgstr "SMPTE Cuadros/segundo" + +#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130 +msgid "SMPTE Minutes" +msgstr "" + +#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132 +#, fuzzy +msgid "Seconds" +msgstr "Minutos:Segundos" + +#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134 +#, fuzzy +msgid "Minutes" +msgstr "Salidas Principales" + +#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106 +msgid "Beats/32" +msgstr "Pulsos/32" + +#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104 +msgid "Beats/16" +msgstr "Pulsos/16" + +#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102 +msgid "Beats/8" +msgstr "Pulsos/8" + +#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100 +msgid "Beats/4" +msgstr "Pulsos/4" + +#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098 +msgid "Beats/3" +msgstr "Pulsos/3" + +#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108 +msgid "Beats" +msgstr "Pulsos" + +#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110 +msgid "Bars" +msgstr "Compaces" + +#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112 +msgid "Marks" +msgstr "Marcas" + +#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114 +#: gtk_ardour/editor.cc:4182 +msgid "Edit Cursor" +msgstr "Cursor de Edicin" + +#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116 +msgid "Region starts" +msgstr "Comienzos de regin" + +#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118 +msgid "Region ends" +msgstr "Fines de regin" + +#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122 +msgid "Region syncs" +msgstr "Sincronizaciones de region" + +#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120 +msgid "Region bounds" +msgstr "Bordes de regin" + +#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153 +#: gtk_ardour/time_axis_view.cc:449 +msgid "Normal" +msgstr "Normal" + +#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155 +#, fuzzy +msgid "Magnetic" +msgstr "Magn�ico" + +#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174 +#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237 +msgid "Left" +msgstr "Izquierdo" + +#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176 +#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238 +msgid "Right" +msgstr "Derecho" + +#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178 +msgid "Center" +msgstr "Centro" + +#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180 +msgid "Playhead" +msgstr "Barra de reproduccin" + +#: gtk_ardour/editor.cc:201 +msgid "Mins:Secs" +msgstr "Mins:Segs" + +#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353 +msgid "Frames" +msgstr "Cuadros" + +#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373 +msgid "Tempo" +msgstr "Tempo" + +#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367 +msgid "Meter" +msgstr "Vmetro" + +#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379 +#, fuzzy +msgid "Location Markers" +msgstr "Marcadores de localizacin" + +#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385 +#, fuzzy +msgid "Range Markers" +msgstr "Marcadores de intervalo" + +#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391 +msgid "Loop/Punch Ranges" +msgstr "" + +#: gtk_ardour/editor.cc:221 +msgid "" +"editor\n" +"mixer" +msgstr "" + +#: gtk_ardour/editor.cc:232 +msgid "range" +msgstr "intervalo" + +#: gtk_ardour/editor.cc:233 +msgid "object" +msgstr "objeto" + +#: gtk_ardour/editor.cc:235 +msgid "zoom" +msgstr "zoom" + +#: gtk_ardour/editor.cc:236 +msgid "timefx" +msgstr "" + +#: gtk_ardour/editor.cc:237 +msgid "listen" +msgstr "" + +#: gtk_ardour/editor.cc:239 +msgid "mode" +msgstr "modo" + +#: gtk_ardour/editor.cc:240 +msgid "automation" +msgstr "automatizacin" + +#: gtk_ardour/editor.cc:242 +msgid "Edit Mode" +msgstr "Modo de edicin" + +#: gtk_ardour/editor.cc:243 +msgid "Snap To" +msgstr "Ajustar a" + +#: gtk_ardour/editor.cc:244 +#, fuzzy +msgid "Snap Mode" +msgstr "Modo de ajuste" + +#: gtk_ardour/editor.cc:245 +msgid "Zoom Focus" +msgstr "Foco de Zoom" + +#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364 +#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579 +msgid "Nudge" +msgstr "Retocar" + +#: gtk_ardour/editor.cc:511 +msgid "Zoom in" +msgstr "Acercar" + +#: gtk_ardour/editor.cc:512 +msgid "Zoom out" +msgstr "Alejar" + +#: gtk_ardour/editor.cc:517 +msgid "Zoom to session" +msgstr "Mostrar toda la sesin" + +#: gtk_ardour/editor.cc:536 +msgid "Zoom Span" +msgstr "Alcance de zoom" + +#: gtk_ardour/editor.cc:566 +msgid "Edit Groups" +msgstr "Editar Grupos" + +#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142 +msgid "-all-" +msgstr "-todo-" + +#: gtk_ardour/editor.cc:718 +msgid "Nudge region/selection forwards" +msgstr "Retocar regin/selecin adelante" + +#: gtk_ardour/editor.cc:719 +msgid "Nudge region/selection backwards" +msgstr "Retocar regin/selecin atr�" + +#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308 +msgid "ardour: editor" +msgstr "" + +#: gtk_ardour/editor.cc:729 +msgid "ardour_editor" +msgstr "" + +#: gtk_ardour/editor.cc:846 +msgid "VerboseCanvasCursor" +msgstr "" + +#: gtk_ardour/editor.cc:1405 +msgid "FirstActionMessage" +msgstr "" + +#: gtk_ardour/editor.cc:1407 +msgid "Start a new session\n" +msgstr "Iniciar una nueva sesin\n" + +#: gtk_ardour/editor.cc:1408 +msgid "via Session menu" +msgstr "via men de Sesin" + +#: gtk_ardour/editor.cc:1703 +msgid "ardour: editor: " +msgstr "" + +#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796 +#: gtk_ardour/editor_markers.cc:797 +msgid "Loop" +msgstr "c�lico" + +#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810 +#: gtk_ardour/editor_markers.cc:823 +msgid "Punch" +msgstr "Insercin" + +#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688 +msgid "programming error: fade in canvas item has no regionview data pointer!" +msgstr "" + +#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986 +#: gtk_ardour/redirect_box.cc:401 +msgid "Deactivate" +msgstr "Desactivar" + +#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988 +#: gtk_ardour/redirect_box.cc:398 +msgid "Activate" +msgstr "Activar" + +#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993 +#, fuzzy +msgid "Linear" +msgstr "linear" + +#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994 +#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734 +#: gtk_ardour/option_editor.cc:796 +#, fuzzy +msgid "Slowest" +msgstr "Menor" + +#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995 +#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735 +#: gtk_ardour/option_editor.cc:798 +#, fuzzy +msgid "Slow" +msgstr "Solo" + +#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996 +#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737 +#: gtk_ardour/option_editor.cc:802 +#, fuzzy +msgid "Fast" +msgstr "Fades" + +#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997 +#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739 +#: gtk_ardour/option_editor.cc:806 +#, fuzzy +msgid "Fastest" +msgstr "r�ido" + +#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113 +msgid "Freeze" +msgstr "Unir regiones" + +#: gtk_ardour/editor.cc:2109 +msgid "Unfreeze" +msgstr "Separar regiones" + +#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328 +#, fuzzy +msgid "Unmute" +msgstr "mudo" + +#: gtk_ardour/editor.cc:2247 +msgid "Convert to short" +msgstr "" + +#: gtk_ardour/editor.cc:2249 +msgid "Convert to full" +msgstr "" + +#: gtk_ardour/editor.cc:2260 +#, fuzzy +msgid "Crossfade" +msgstr "editar fade in" + +#: gtk_ardour/editor.cc:2303 +msgid "Popup region editor" +msgstr "Editor de regiones" + +#: gtk_ardour/editor.cc:2304 +#, fuzzy +msgid "Raise to top layer" +msgstr "Elevar regin a la capa m� alta" + +#: gtk_ardour/editor.cc:2305 +#, fuzzy +msgid "Lower to bottom layer" +msgstr "Enviar regin a capa m� baja" + +#: gtk_ardour/editor.cc:2307 +msgid "Define sync point" +msgstr "Definir punto de sincron�" + +#: gtk_ardour/editor.cc:2308 +msgid "Remove sync point" +msgstr "Remover punto de sincron�" + +#: gtk_ardour/editor.cc:2313 +#, fuzzy +msgid "Bounce" +msgstr "intervalo" + +#: gtk_ardour/editor.cc:2323 +#, fuzzy +msgid "Lock" +msgstr "bloquear" + +#: gtk_ardour/editor.cc:2324 +#, fuzzy +msgid "Unlock" +msgstr "Desbloquear" + +#: gtk_ardour/editor.cc:2334 +#, fuzzy +msgid "Original position" +msgstr "Posicin original" + +#: gtk_ardour/editor.cc:2340 +msgid "Toggle envelope visibility" +msgstr "" + +#: gtk_ardour/editor.cc:2341 +#, fuzzy +msgid "Toggle envelope active" +msgstr "activar" + +#: gtk_ardour/editor.cc:2345 +#, fuzzy +msgid "DeNormalize" +msgstr "Normalizar" + +#: gtk_ardour/editor.cc:2347 +#, fuzzy +msgid "Normalize" +msgstr "Normalizar" + +#: gtk_ardour/editor.cc:2350 +#, fuzzy +msgid "Reverse" +msgstr "Invertir" + +#: gtk_ardour/editor.cc:2359 +#, fuzzy +msgid "Nudge fwd" +msgstr "Retocar" + +#: gtk_ardour/editor.cc:2360 +#, fuzzy +msgid "Nudge bwd" +msgstr "Retocar" + +#: gtk_ardour/editor.cc:2361 +msgid "Nudge fwd by capture offset" +msgstr "" + +#: gtk_ardour/editor.cc:2362 +msgid "Nudge bwd by capture offset" +msgstr "" + +#: gtk_ardour/editor.cc:2371 +msgid "Start to edit cursor" +msgstr "Desde principio hasta cursor de edicin" + +#: gtk_ardour/editor.cc:2372 +msgid "Edit cursor to end" +msgstr "Desde cursor de edicin hasta final" + +#: gtk_ardour/editor.cc:2374 +msgid "Trim" +msgstr "Cortar" + +#: gtk_ardour/editor.cc:2377 +msgid "Split" +msgstr "Separar" + +#: gtk_ardour/editor.cc:2380 +msgid "Make mono regions" +msgstr "Crear regiones mono" + +#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428 +msgid "Duplicate" +msgstr "Duplicar" + +#: gtk_ardour/editor.cc:2384 +msgid "Fill Track" +msgstr "Llenar Pista" + +#: gtk_ardour/editor.cc:2388 +#, fuzzy +msgid "Destroy" +msgstr "Destruir" + +#: gtk_ardour/editor.cc:2418 +#, fuzzy +msgid "Play range" +msgstr "Reproducir el intervalo cont�uamente" + +#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446 +#, fuzzy +msgid "Loop range" +msgstr "rango de reproduccin cont�ua" + +#: gtk_ardour/editor.cc:2421 +#, fuzzy +msgid "Create chunk from range" +msgstr "Crear trecho a partir de seleccin" + +#: gtk_ardour/editor.cc:2423 +msgid "Create Region" +msgstr "Crear Regin" + +#: gtk_ardour/editor.cc:2424 +msgid "Separate Region" +msgstr "Separar Regin" + +#: gtk_ardour/editor.cc:2425 +#, fuzzy +msgid "Crop Region to range" +msgstr "Acortar regin hasta la seleccin" + +#: gtk_ardour/editor.cc:2426 +#, fuzzy +msgid "Bounce range" +msgstr "intervalo" + +#: gtk_ardour/editor.cc:2432 +#, fuzzy +msgid "Fill range w/Region" +msgstr "Crear Regin" + +#: gtk_ardour/editor.cc:2434 +#, fuzzy +msgid "Range" +msgstr "intervalo" + +#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538 +#, fuzzy +msgid "Play from edit cursor" +msgstr "Reproducir desde el cursor" + +#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539 +msgid "Play from start" +msgstr "Reproducir desde el principio" + +#: gtk_ardour/editor.cc:2451 +#, fuzzy +msgid "Play region" +msgstr "Reproducir Regin" + +#: gtk_ardour/editor.cc:2453 +#, fuzzy +msgid "Loop Region" +msgstr "Reproducir regin cont�uamente" + +#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540 +#: gtk_ardour/library_ui.cc:972 +msgid "Play" +msgstr "Reproducir" + +#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548 +#, fuzzy +msgid "Select All in track" +msgstr "Seleccionar todo dentro de pista" + +#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549 +#, fuzzy +msgid "Select All" +msgstr "Seleccionar todo" + +#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550 +msgid "Invert in track" +msgstr "Invertir dentro de pista" + +#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551 +#, fuzzy +msgid "Invert" +msgstr "Invertir" + +#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553 +#, fuzzy +msgid "Select loop range" +msgstr "seleccionar rango de zoom" + +#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554 +#, fuzzy +msgid "Select punch range" +msgstr "Seleccionar intervalo actual" + +#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565 +#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369 +msgid "Cut" +msgstr "Cortar" + +#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566 +#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371 +msgid "Copy" +msgstr "Copiar" + +#: gtk_ardour/editor.cc:2482 +#, fuzzy +msgid "Paste at edit cursor" +msgstr "Desde principio hasta cursor de edicin" + +#: gtk_ardour/editor.cc:2483 +#, fuzzy +msgid "Paste at mouse" +msgstr "usar salidas Master" + +#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923 +msgid "Align" +msgstr "Alinear" + +#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925 +msgid "Align Relative" +msgstr "Alinear relativamente" + +#: gtk_ardour/editor.cc:2492 +msgid "Insert chunk" +msgstr "Insertar trecho" + +#: gtk_ardour/editor.cc:2496 +#, fuzzy +msgid "New Region from range" +msgstr "Nueva region a partir de seleccin" + +#: gtk_ardour/editor.cc:2497 +#, fuzzy +msgid "Separate Range" +msgstr "Separar Regin" + +#: gtk_ardour/editor.cc:2507 +msgid "Insert Region" +msgstr "Insertar Regin" + +#: gtk_ardour/editor.cc:2508 +msgid "Insert external sndfile" +msgstr "Insertar archivo de audio externo" + +#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438 +msgid "Import" +msgstr "Importar" + +#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574 +msgid "Nudge entire track fwd" +msgstr "Retocar toda la pista adelante" + +#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575 +msgid "Nudge track after edit cursor fwd" +msgstr "Retocar pista desde cursor de edicin adelante" + +#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576 +msgid "Nudge entire track bwd" +msgstr "Retocar toda la pista atr�" + +#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577 +msgid "Nudge track after edit cursor bwd" +msgstr "Retocar toda la pista, desde cursor de edicin atr�" + +#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920 +#: gtk_ardour/redirect_box.cc:373 +msgid "Paste" +msgstr "Pegar" + +#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645 +#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799 +msgid "add marker" +msgstr "agregar marcador" + +#: gtk_ardour/editor.cc:3084 +msgid "select/move objects" +msgstr "selecionar/mover objetos" + +#: gtk_ardour/editor.cc:3085 +msgid "select/move ranges" +msgstr "selecionar/mover intervalos" + +#: gtk_ardour/editor.cc:3086 +msgid "draw gain automation" +msgstr "dibujar automatizacin de volumen" + +#: gtk_ardour/editor.cc:3087 +msgid "select zoom range" +msgstr "seleccionar rango de zoom" + +#: gtk_ardour/editor.cc:3088 +msgid "stretch/shrink regions" +msgstr "estirar/encoger regiones" + +#: gtk_ardour/editor.cc:3089 +#, fuzzy +msgid "listen to specific regions" +msgstr "Reproducir regin seleccionada cont�uamente" + +#: gtk_ardour/editor.cc:3213 +msgid "Start:" +msgstr "Inicio:" + +#: gtk_ardour/editor.cc:3214 +msgid "End:" +msgstr "Final:" + +#: gtk_ardour/editor.cc:3215 +msgid "Edit:" +msgstr "Editar:" + +#: gtk_ardour/editor.cc:3429 +msgid "incorrectly formatted URI list, ignored" +msgstr "" + +#: gtk_ardour/editor.cc:3611 +#, fuzzy +msgid "set selected trackview" +msgstr "Insertar seleccin" + +#: gtk_ardour/editor.cc:3647 +#, fuzzy +msgid "set selected control point" +msgstr "Remover punto de sincron�" + +#: gtk_ardour/editor.cc:3719 +#, fuzzy +msgid "set selected regionview" +msgstr "Reproducir regin seleccionada cont�uamente" + +#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835 +#, fuzzy +msgid "set selected regions" +msgstr "Reproducir regin seleccionada cont�uamente" + +#: gtk_ardour/editor.cc:3891 +msgid "Undo" +msgstr "Deshacer" + +#: gtk_ardour/editor.cc:3893 +msgid "Undo (%1)" +msgstr "Deshacer (%1)" + +#: gtk_ardour/editor.cc:3903 +msgid "Redo" +msgstr "Rehacer" + +#: gtk_ardour/editor.cc:3905 +msgid "Redo (%1)" +msgstr "Rehacer (%1)" + +#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946 +msgid "... as new track" +msgstr "" + +#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947 +#, fuzzy +msgid "... as new region" +msgstr "normalizar regiones" + +#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452 +msgid "Import audio (copy)" +msgstr "Importar audio (copiar)" + +#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457 +msgid "Embed audio (link)" +msgstr "Linquear a a archivo" + +#: gtk_ardour/editor.cc:3953 +#, fuzzy +msgid "Remove last capture" +msgstr "Quitar ltima captura" + +#: gtk_ardour/editor.cc:3974 +msgid "Duplicate how many times?" +msgstr "Duplicar cuantas veces?" + +#: gtk_ardour/editor.cc:4550 +msgid "" +"Playlist %1 is currently unused.\n" +"If left alone, no audio files used by it will be cleaned.\n" +"If deleted, audio files used by it alone by will cleaned." +msgstr "" + +#: gtk_ardour/editor.cc:4555 +#, fuzzy +msgid "Delete playlist" +msgstr "Nombre a captura de sesin" + +#: gtk_ardour/editor.cc:4556 +#, fuzzy +msgid "Keep playlist" +msgstr "Nombre a captura de sesin" + +#: gtk_ardour/editor.cc:4557 +#, fuzzy +msgid "Cancel cleanup" +msgstr "Limpiar" + +#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258 +#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290 +msgid "" +"programming error: control point canvas item has no control point object " +"pointer!" +msgstr "" + +#: gtk_ardour/editor_canvas_events.cc:717 +msgid "programming error: line canvas item has no line object pointer!" +msgstr "" + +#: gtk_ardour/editor_canvas_events.cc:744 +#: gtk_ardour/editor_canvas_events.cc:784 +#: gtk_ardour/editor_canvas_events.cc:823 +msgid "programming error: no \"rect\" pointer associated with selection item" +msgstr "" + +#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298 +#: gtk_ardour/mixer_ui.cc:670 +msgid "Show All" +msgstr "Mostrar Todo" + +#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299 +#: gtk_ardour/mixer_ui.cc:671 +msgid "Hide All" +msgstr "Ocultar Todo" + +#: gtk_ardour/editor_edit_groups.cc:98 +msgid "Name for new edit group" +msgstr "Nombre para nuevo grupo de edicin" + +#: gtk_ardour/editor_export_audio.cc:60 +msgid "" +"There is no range to export.\n" +"\n" +"Select a range using the range mouse mode" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707 +msgid "programming error: no ImageFrameView selected" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930 +msgid "programming error: no MarkerView selected" +msgstr "" + +#: gtk_ardour/editor_keys.cc:187 +#, fuzzy +msgid "keyboard selection" +msgstr "Separar Seleccin" + +#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376 +#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526 +#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584 +#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650 +#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700 +#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960 +#: gtk_ardour/editor_mouse.cc:4075 +msgid "programming error: marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681 +msgid "remove marker" +msgstr "quitar marcador" + +#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494 +#, fuzzy +msgid "Locate to" +msgstr "Localizar a" + +#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495 +#, fuzzy +msgid "Play from" +msgstr "Reproducir desde" + +#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496 +#, fuzzy +msgid "Set from playhead" +msgstr "Ubicar desde barra de reproduccin" + +#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497 +#, fuzzy +msgid "Set from range" +msgstr "selecionar intervalo de reproduccin cont�ua" + +#: gtk_ardour/editor_markers.cc:479 +#, fuzzy +msgid "Set Loop Range" +msgstr "selecionar intervalo de reproduccin cont�ua" + +#: gtk_ardour/editor_markers.cc:480 +msgid "Set Punch Range" +msgstr "Seleccionar intervalo de punch" + +#: gtk_ardour/editor_markers.cc:736 +msgid "ardour: rename mark" +msgstr "ardour: renombrar marca" + +#: gtk_ardour/editor_markers.cc:738 +#, fuzzy +msgid "ardour: rename range" +msgstr "ardour: renombrar regin" + +#: gtk_ardour/editor_markers.cc:792 +#, fuzzy +msgid "set loop range" +msgstr "seleccionar rango de zoom" + +#: gtk_ardour/editor_markers.cc:818 +#, fuzzy +msgid "set punch range" +msgstr "Seleccionar intervalo actual" + +#: gtk_ardour/editor_mouse.cc:99 +msgid "Editor::event_frame() used on unhandled event type %1" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1555 +msgid "programming error: start_grab called without drag item" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1760 +#, fuzzy +msgid "change fade in length" +msgstr "editar fade in" + +#: gtk_ardour/editor_mouse.cc:1778 +msgid "programming error: fade out canvas item has no regionview data pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1852 +#, fuzzy +msgid "change fade out length" +msgstr "agregar salida" + +#: gtk_ardour/editor_mouse.cc:1871 +msgid "programming error: cursor canvas item has no cursor data pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470 +msgid "" +"programming error: meter marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2163 +#, fuzzy +msgid "move meter mark" +msgstr "quitar marcador" + +#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335 +#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439 +msgid "" +"programming error: tempo marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340 +#: gtk_ardour/editor_tempodisplay.cc:425 +msgid "programming error: marker for tempo is not a tempo marker!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2245 +#, fuzzy +msgid "move tempo mark" +msgstr "quitar marcador" + +#: gtk_ardour/editor_mouse.cc:2388 +msgid "programming error: line canvas item has no line pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2497 +#, fuzzy +msgid "move region(s)" +msgstr "invertir regiones" + +#: gtk_ardour/editor_mouse.cc:2509 +msgid "Drag region copy" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2579 +#, fuzzy +msgid "copy region(s)" +msgstr "normalizar regiones" + +#: gtk_ardour/editor_mouse.cc:2612 +#, fuzzy +msgid "Drag region brush" +msgstr "normalizar regiones" + +#: gtk_ardour/editor_mouse.cc:3425 +#, fuzzy +msgid "selection grab" +msgstr "Seleccin" + +#: gtk_ardour/editor_mouse.cc:3571 +#, fuzzy +msgid "range selection" +msgstr "Reproducir seleccin" + +#: gtk_ardour/editor_mouse.cc:3587 +#, fuzzy +msgid "trim selection start" +msgstr "Desde locacin" + +#: gtk_ardour/editor_mouse.cc:3603 +#, fuzzy +msgid "trim selection end" +msgstr "Desde locacin" + +#: gtk_ardour/editor_mouse.cc:3620 +#, fuzzy +msgid "move selection" +msgstr "Grabar seleccin" + +#: gtk_ardour/editor_mouse.cc:3995 +#, fuzzy +msgid "Start point trim" +msgstr "Desde principio hasta cursor de edicin" + +#: gtk_ardour/editor_mouse.cc:4023 +msgid "End point trim" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:4062 +msgid "trimmed region" +msgstr "regin acortada" + +#: gtk_ardour/editor_mouse.cc:4203 +#, fuzzy +msgid "new range marker" +msgstr "agregar un marcador de regin" + +#: gtk_ardour/editor_mouse.cc:4422 +#, fuzzy +msgid "select regions" +msgstr "Reproducir regin seleccionada cont�uamente" + +#: gtk_ardour/editor_mouse.cc:4451 +msgid "Name for region:" +msgstr "Nombre para regin:" + +#: gtk_ardour/editor_mouse.cc:4517 +msgid "timestretch" +msgstr "" + +#: gtk_ardour/editor_ops.cc:117 +#, fuzzy +msgid "split" +msgstr "Separar" + +#: gtk_ardour/editor_ops.cc:153 +#, fuzzy +msgid "remove region" +msgstr "invertir regiones" + +#: gtk_ardour/editor_ops.cc:172 +msgid "" +" This is destructive, will possibly delete audio files\n" +"It cannot be undone\n" +"Do you really want to destroy %1 ?" +msgstr "" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "these regions" +msgstr "invertir regiones" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "this region" +msgstr "enmudecer a esta regin" + +#: gtk_ardour/editor_ops.cc:179 +#, fuzzy +msgid "Yes, destroy them." +msgstr "Si, eliminar." + +#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434 +#, fuzzy +msgid "Yes, destroy it." +msgstr "Si, eliminar." + +#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435 +#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300 +#, fuzzy +msgid "No, do nothing." +msgstr "No, no hacer nada." + +#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307 +#, fuzzy +msgid "extend selection" +msgstr "Separar Seleccin" + +#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357 +#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427 +msgid "nudge forward" +msgstr "" + +#: gtk_ardour/editor_ops.cc:491 +msgid "build_region_boundary_cache called with snap_type = %1" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1305 +#, fuzzy +msgid "set selection from range" +msgstr "Nueva region a partir de seleccin" + +#: gtk_ardour/editor_ops.cc:1421 +msgid "clear markers" +msgstr "borrar marcadores" + +#: gtk_ardour/editor_ops.cc:1433 +msgid "clear ranges" +msgstr "borrar intervalos" + +#: gtk_ardour/editor_ops.cc:1452 +msgid "clear locations" +msgstr "borrar localizaciones" + +#: gtk_ardour/editor_ops.cc:1503 +#, fuzzy +msgid "insert dragged region" +msgstr "Insertar Regin" + +#: gtk_ardour/editor_ops.cc:1538 +#, fuzzy +msgid "insert region" +msgstr "Insertar Regin" + +#: gtk_ardour/editor_ops.cc:1744 +msgid "ardour: rename region" +msgstr "ardour: renombrar regin" + +#: gtk_ardour/editor_ops.cc:1891 +msgid "You can't import an audiofile until you have a session loaded." +msgstr "No puede importar un archivo a menos que abra o cree una sesin" + +#: gtk_ardour/editor_ops.cc:1901 +#, fuzzy +msgid "Import selected as tracks" +msgstr "Importar seleccin" + +#: gtk_ardour/editor_ops.cc:1904 +#, fuzzy +msgid "Import selected to region list" +msgstr "Reproducir regin seleccionada cont�uamente" + +#: gtk_ardour/editor_ops.cc:1933 +msgid "ardour: audio import in progress" +msgstr "ardour: importando archivo de audio" + +#: gtk_ardour/editor_ops.cc:1937 +msgid "Cancel Import" +msgstr "Cancelar importacin" + +#: gtk_ardour/editor_ops.cc:1944 +#, fuzzy +msgid "ardour: importing %1" +msgstr "ardour: exportar" + +#: gtk_ardour/editor_ops.cc:1990 +#, fuzzy +msgid "%1 it anyway" +msgstr "Linquear de todas formas" + +#: gtk_ardour/editor_ops.cc:1996 +#, fuzzy +msgid "Don't %1 it" +msgstr "No %1" + +#: gtk_ardour/editor_ops.cc:1997 +msgid "%1 all without questions" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1998 +#, fuzzy +msgid "Cancel entire import" +msgstr "Cancelar importacin" + +#: gtk_ardour/editor_ops.cc:2004 +#, fuzzy +msgid "" +"%1\n" +"This audiofile's sample rate doesn't match the session sample rate!" +msgstr "La frecuencia de muestreo de este archivo difiere de la de la sesin!" + +#: gtk_ardour/editor_ops.cc:2032 +#, fuzzy +msgid "You can't embed an audiofile until you have a session loaded." +msgstr "No puede linquear a un archivo a menos que abra o cree una sesin" + +#: gtk_ardour/editor_ops.cc:2039 +msgid "Add to External Region list" +msgstr "Agregar a lista externa de regiones" + +#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210 +#: gtk_ardour/editor_ops.cc:2286 +msgid "Editor: cannot open file \"%1\" (%2)" +msgstr "Editor: no se pudo abrir el archivo \"%1\" (%2)" + +#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312 +msgid "could not open %1" +msgstr "no se pudo abrir %1" + +#: gtk_ardour/editor_ops.cc:2171 +#, fuzzy +msgid "Insert selected as new tracks" +msgstr "Insertar seleccin" + +#: gtk_ardour/editor_ops.cc:2186 +msgid "Insert selected" +msgstr "Insertar seleccin" + +#: gtk_ardour/editor_ops.cc:2327 +#, fuzzy +msgid "insert sndfile" +msgstr "Insertar archivo de audio externo" + +#: gtk_ardour/editor_ops.cc:2464 +#, fuzzy +msgid "separate" +msgstr "Separar Regin" + +#: gtk_ardour/editor_ops.cc:2528 +#, fuzzy +msgid "trim to selection" +msgstr "Desde locacin" + +#: gtk_ardour/editor_ops.cc:2568 +msgid "region fill" +msgstr "" + +#: gtk_ardour/editor_ops.cc:2626 +#, fuzzy +msgid "fill selection" +msgstr "Reproducir seleccin cont�uamente" + +#: gtk_ardour/editor_ops.cc:2650 +msgid "Place the edit cursor at the desired sync point" +msgstr "Coloque el cursor de edicin en el punto de sincron� deseado" + +#: gtk_ardour/editor_ops.cc:2656 +#, fuzzy +msgid "set sync from edit cursor" +msgstr "Reproducir desde el cursor" + +#: gtk_ardour/editor_ops.cc:2668 +#, fuzzy +msgid "remove sync" +msgstr "Remover punto de sincron�" + +#: gtk_ardour/editor_ops.cc:2682 +#, fuzzy +msgid "naturalize" +msgstr "Normalizar" + +#: gtk_ardour/editor_ops.cc:2746 +#, fuzzy +msgid "align selection (relative)" +msgstr "Alinear relativamente" + +#: gtk_ardour/editor_ops.cc:2774 +#, fuzzy +msgid "align selection" +msgstr "Grabar seleccin" + +#: gtk_ardour/editor_ops.cc:2786 +#, fuzzy +msgid "align region" +msgstr "normalizar regiones" + +#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858 +#, fuzzy +msgid "trim to edit" +msgstr "Desde principio hasta cursor de edicin" + +#: gtk_ardour/editor_ops.cc:2909 +#, fuzzy +msgid "ardour: freeze" +msgstr "ardour: renombrar regin" + +#: gtk_ardour/editor_ops.cc:2914 +#, fuzzy +msgid "Cancel Freeze" +msgstr "Cancelar" + +#: gtk_ardour/editor_ops.cc:2951 +#, fuzzy +msgid "bounce range" +msgstr "intervalo" + +#: gtk_ardour/editor_ops.cc:3004 +#, fuzzy +msgid "cut" +msgstr "cortar" + +#: gtk_ardour/editor_ops.cc:3007 +#, fuzzy +msgid "copy" +msgstr "copiar" + +#: gtk_ardour/editor_ops.cc:3020 +#, fuzzy +msgid " objects" +msgstr "objetos" + +#: gtk_ardour/editor_ops.cc:3046 +#, fuzzy +msgid " range" +msgstr "intervalo" + +#: gtk_ardour/editor_ops.cc:3201 +#, fuzzy +msgid "paste" +msgstr "Pegar" + +#: gtk_ardour/editor_ops.cc:3236 +#, fuzzy +msgid "paste chunk" +msgstr "Crear trecho" + +#: gtk_ardour/editor_ops.cc:3276 +#, fuzzy +msgid "duplicate region" +msgstr "Reproducir regin seleccionada cont�uamente" + +#: gtk_ardour/editor_ops.cc:3309 +#, fuzzy +msgid "duplicate selection" +msgstr "Grabar seleccin" + +#: gtk_ardour/editor_ops.cc:3349 +#, fuzzy +msgid "clear playlist" +msgstr "Nombre a captura de sesin" + +#: gtk_ardour/editor_ops.cc:3378 +#, fuzzy +msgid "nudge track" +msgstr "Ocultar esta pista" + +#: gtk_ardour/editor_ops.cc:3431 +#, fuzzy +msgid "" +"Do you really want to destroy the last capture?\n" +"(This is destructive and cannot be undone)" +msgstr "" +"Realmente desea quitar el bus \"%1\" ?\n" +"(no podr�deshacer este cambio)" + +#: gtk_ardour/editor_ops.cc:3463 +#, fuzzy +msgid "normalize" +msgstr "Normalizar" + +#: gtk_ardour/editor_ops.cc:3510 +#, fuzzy +msgid "reverse regions" +msgstr "invertir regiones" + +#: gtk_ardour/editor_region_list.cc:223 +#, fuzzy +msgid "hidden" +msgstr "Oculto" + +#: gtk_ardour/editor_region_list.cc:408 +msgid "Show all" +msgstr "Mostrar todo" + +#: gtk_ardour/editor_region_list.cc:417 +msgid "Ascending" +msgstr "Ascendente" + +#: gtk_ardour/editor_region_list.cc:419 +msgid "Descending" +msgstr "Descendente" + +#: gtk_ardour/editor_region_list.cc:423 +msgid "By Region Name" +msgstr "Por Nombre de Regin" + +#: gtk_ardour/editor_region_list.cc:425 +msgid "By Region Length" +msgstr "Por Tamao de Regin" + +#: gtk_ardour/editor_region_list.cc:427 +msgid "By Region Position" +msgstr "Por Posicin de regin" + +#: gtk_ardour/editor_region_list.cc:429 +msgid "By Region Timestamp" +msgstr "Por fecha de Regin" + +#: gtk_ardour/editor_region_list.cc:431 +msgid "By Region Start in File" +msgstr "Por inicio de regin en archivo" + +#: gtk_ardour/editor_region_list.cc:433 +msgid "By Region End in File" +msgstr "Por fin de regin en archivo" + +#: gtk_ardour/editor_region_list.cc:435 +msgid "By Source File Name" +msgstr "Por nombre de archivo" + +#: gtk_ardour/editor_region_list.cc:437 +msgid "By Source File Length" +msgstr "Por tamao de archivo" + +#: gtk_ardour/editor_region_list.cc:439 +msgid "By Source File Creation Date" +msgstr "Por fecha de creacin" + +#: gtk_ardour/editor_region_list.cc:441 +msgid "By Source Filesystem" +msgstr "Por sistema de archivos" + +#: gtk_ardour/editor_region_list.cc:444 +msgid "Sorting" +msgstr "Orden" + +#: gtk_ardour/editor_region_list.cc:808 +msgid "Regions/length" +msgstr "Regiones/tamao" + +#: gtk_ardour/editor_region_list.cc:812 +msgid "Regions/position" +msgstr "Regiones/posicin" + +#: gtk_ardour/editor_region_list.cc:816 +msgid "Regions/creation" +msgstr "Regiones/creacin" + +#: gtk_ardour/editor_region_list.cc:820 +msgid "Regions/start" +msgstr "Regiones/in�io" + +#: gtk_ardour/editor_region_list.cc:824 +msgid "Regions/end" +msgstr "Regiones/final" + +#: gtk_ardour/editor_region_list.cc:828 +msgid "Regions/file name" +msgstr "Regiones/nombre del archivo" + +#: gtk_ardour/editor_region_list.cc:832 +msgid "Regions/file size" +msgstr "Regiones/tamao del archivo" + +#: gtk_ardour/editor_region_list.cc:836 +msgid "Regions/file date" +msgstr "Regiones/fecha del archivo" + +#: gtk_ardour/editor_region_list.cc:840 +msgid "Regions/file system" +msgstr "Regiones/sistema de archivos" + +#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73 +#: gtk_ardour/editor_route_list.cc:231 +msgid "editor" +msgstr "editor" + +#: gtk_ardour/editor_route_list.cc:300 +msgid "Show All AbstractTracks" +msgstr "Mostrar todas las pistas de Audio" + +#: gtk_ardour/editor_route_list.cc:301 +msgid "Hide All AbstractTracks" +msgstr "Ocultar todas las pistas de Audio" + +#: gtk_ardour/editor_route_list.cc:302 +msgid "Show All AudioBus" +msgstr "Mostrar todos los Buses" + +#: gtk_ardour/editor_route_list.cc:303 +msgid "Hide All AudioBus" +msgstr "Ocultar todos los Buses" + +#: gtk_ardour/editor_rulers.cc:311 +#, fuzzy +msgid "New location marker" +msgstr "Nuevo marcador de localizacin" + +#: gtk_ardour/editor_rulers.cc:312 +#, fuzzy +msgid "Clear all locations" +msgstr "Quitar todas las localizaciones" + +#: gtk_ardour/editor_rulers.cc:317 +#, fuzzy +msgid "Clear all ranges" +msgstr "Quitar todas las selecciones" + +#: gtk_ardour/editor_rulers.cc:326 +#, fuzzy +msgid "New Tempo" +msgstr "Nuevo tempo" + +#: gtk_ardour/editor_rulers.cc:327 +#, fuzzy +msgid "Clear tempo" +msgstr "Resetear tempo" + +#: gtk_ardour/editor_rulers.cc:332 +#, fuzzy +msgid "New Meter" +msgstr "Nuevo Medidor" + +#: gtk_ardour/editor_rulers.cc:333 +#, fuzzy +msgid "Clear meter" +msgstr "Resetear Medidor" + +#: gtk_ardour/editor_rulers.cc:341 +#, fuzzy +msgid "Min:Secs" +msgstr "Mins:Segs" + +#: gtk_ardour/editor_selection_list.cc:117 +msgid "name for chunk:" +msgstr "nombre para trecho" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Create chunk" +msgstr "Crear trecho" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Forget it" +msgstr "Olvidarlo" + +#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295 +msgid "add" +msgstr "agregar" + +#: gtk_ardour/editor_tempodisplay.cc:276 +#, fuzzy +msgid "add tempo mark" +msgstr "agregar un marcador de regin" + +#: gtk_ardour/editor_tempodisplay.cc:318 +#, fuzzy +msgid "add meter mark" +msgstr "agregar un marcador de regin" + +#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383 +msgid "done" +msgstr "listo" + +#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404 +msgid "replace tempo mark" +msgstr "" + +#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475 +msgid "programming error: marker for meter is not a meter marker!" +msgstr "" + +#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487 +#, fuzzy +msgid "remove tempo mark" +msgstr "quitar marcador" + +#: gtk_ardour/editor_timefx.cc:50 +msgid "Quick but Ugly" +msgstr "R�ido pero pobre" + +#: gtk_ardour/editor_timefx.cc:51 +msgid "Skip Anti-aliasing" +msgstr "No usar Anti-aliasing" + +#: gtk_ardour/editor_timefx.cc:53 +msgid "Stretch/Shrink it" +msgstr "Estirar/Encoger esto" + +#: gtk_ardour/editor_timefx.cc:57 +msgid "ardour: timestretch" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:58 +msgid "TimeStretchDialog" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83 +#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85 +msgid "TimeStretchButton" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:86 +msgid "TimeStretchProgress" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:151 +msgid "timestretch cannot be started - thread creation error" +msgstr "" + +#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410 +#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189 +msgid "22.05kHz" +msgstr "22.05kHz" + +#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413 +#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949 +#: gtk_ardour/export_dialog.cc:1191 +msgid "44.1kHz" +msgstr "44.1kHz" + +#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416 +#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193 +msgid "48kHz" +msgstr "48kHz" + +#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419 +#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195 +msgid "88.2kHz" +msgstr "88.2kHz" + +#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422 +#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197 +msgid "96kHz" +msgstr "96kHz" + +#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425 +#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199 +msgid "192kHz" +msgstr "192kHz" + +#: gtk_ardour/export_dialog.cc:73 +msgid "best" +msgstr "excelente" + +#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964 +msgid "fastest" +msgstr "r�ido" + +#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966 +msgid "linear" +msgstr "linear" + +#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968 +msgid "better" +msgstr "bueno" + +#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970 +msgid "intermediate" +msgstr "intermedio" + +#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979 +msgid "Rectangular" +msgstr "Rectangular" + +#: gtk_ardour/export_dialog.cc:84 +msgid "Shaped Noise" +msgstr "Perfil de Ru�o" + +#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981 +msgid "Triangular" +msgstr "Triangular" + +#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336 +msgid "stereo" +msgstr "est�eo" + +#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497 +#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219 +#: gtk_ardour/utils.cc:334 +msgid "mono" +msgstr "mono" + +#: gtk_ardour/export_dialog.cc:97 +msgid "CUE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:98 +msgid "TOC" +msgstr "" + +#: gtk_ardour/export_dialog.cc:106 +msgid "FORMAT" +msgstr "FORMATO" + +#: gtk_ardour/export_dialog.cc:107 +msgid "SAMPLE RATE" +msgstr "FRECUENCIA DE MUESTREO" + +#: gtk_ardour/export_dialog.cc:108 +msgid "CONVERSION QUALITY" +msgstr "CALIDAD DE CONVERSI�" + +#: gtk_ardour/export_dialog.cc:109 +msgid "DITHER TYPE" +msgstr "TIPO DE DITHER" + +#: gtk_ardour/export_dialog.cc:110 +#, fuzzy +msgid "CD MARKER FILE TYPE" +msgstr "TIPO DE ARCHIVO" + +#: gtk_ardour/export_dialog.cc:111 +msgid "CHANNELS" +msgstr "CANALES" + +#: gtk_ardour/export_dialog.cc:112 +msgid "FILE TYPE" +msgstr "TIPO DE ARCHIVO" + +#: gtk_ardour/export_dialog.cc:113 +msgid "SAMPLE FORMAT" +msgstr "FORMATO" + +#: gtk_ardour/export_dialog.cc:114 +msgid "SAMPLE ENDIANNESS" +msgstr "TIPO DE ENDIAN" + +#: gtk_ardour/export_dialog.cc:115 +#, fuzzy +msgid "EXPORT CD MARKER FILE ONLY" +msgstr "TIPO DE ARCHIVO" + +#: gtk_ardour/export_dialog.cc:116 +msgid "EXPORT TO FILE" +msgstr "EXPORTAR A ARCHIVO" + +#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118 +#: gtk_ardour/option_editor.cc:119 +msgid "Browse" +msgstr "Seleccionar" + +#: gtk_ardour/export_dialog.cc:119 +msgid "Specific tracks ..." +msgstr "" + +#: gtk_ardour/export_dialog.cc:131 +msgid "ardour: export" +msgstr "ardour: exportar" + +#: gtk_ardour/export_dialog.cc:132 +msgid "ardour_export" +msgstr "" + +#: gtk_ardour/export_dialog.cc:156 +#, fuzzy +msgid "Output" +msgstr "Salidas" + +#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626 +msgid "Track" +msgstr "Pista" + +#: gtk_ardour/export_dialog.cc:287 +msgid "slereg" +msgstr "" + +#: gtk_ardour/export_dialog.cc:658 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD toc file" +msgstr "" +"Editor: no se puede abrir \"%1\" como archivo de exportacin de marcadores de " +"CD" + +#: gtk_ardour/export_dialog.cc:780 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD cue file" +msgstr "" +"Editor: no se puede abrir \"%1\" como archivo de exportacin de marcadores de " +"CD" + +#: gtk_ardour/export_dialog.cc:799 +msgid "WAV" +msgstr "" + +#: gtk_ardour/export_dialog.cc:1051 +msgid "Stop Export" +msgstr "Cancelar Exportacin" + +#: gtk_ardour/gain_automation_time_axis.cc:60 +#, fuzzy +msgid "add gain automation event" +msgstr "agregar evento de automatizacin a " + +#: gtk_ardour/gain_meter.cc:68 +msgid "Cannot create slider pixmaps" +msgstr "" + +#: gtk_ardour/gain_meter.cc:83 +msgid "dbFS" +msgstr "" + +#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134 +#: gtk_ardour/gain_meter.cc:728 +msgid "pre" +msgstr "" + +#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724 +#, fuzzy +msgid "input" +msgstr "%1 entrada" + +#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732 +#, fuzzy +msgid "post" +msgstr "conector" + +#: gtk_ardour/gain_meter.cc:146 +msgid "tupni" +msgstr "" + +#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470 +#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537 +#, fuzzy +msgid "-inf" +msgstr "entrada" + +#: gtk_ardour/imageframe_socket_handler.cc:127 +msgid "Image Compositor Socket has been shutdown/closed" +msgstr "Se desconect al Compositor de Imagen" + +#: gtk_ardour/imageframe_time_axis.cc:295 +#, fuzzy +msgid "0.5 seconds" +msgstr "Minutos:Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259 +#, fuzzy +msgid "1 seconds" +msgstr "Minutos:Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260 +#, fuzzy +msgid "1.5 seconds" +msgstr "Minutos:Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261 +#, fuzzy +msgid "2 seconds" +msgstr "Minutos:Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262 +#, fuzzy +msgid "2.5 seconds" +msgstr "Minutos:Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263 +#, fuzzy +msgid "3 seconds" +msgstr "Minutos:Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268 +#, fuzzy +msgid "Duration (sec)" +msgstr "normalizar regiones" + +#: gtk_ardour/imageframe_time_axis.cc:310 +#, fuzzy +msgid "Remove Frame" +msgstr "Quitar Campo" + +#: gtk_ardour/imageframe_time_axis.cc:313 +#, fuzzy +msgid "Image Frame" +msgstr "Cuadros" + +#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274 +#, fuzzy +msgid "Rename Track" +msgstr "Renombrar" + +#: gtk_ardour/io_selector.cc:64 +msgid "%1 input" +msgstr "%1 entrada" + +#: gtk_ardour/io_selector.cc:66 +msgid "%1 output" +msgstr "%1 salida" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103 +msgid "Inputs" +msgstr "Entradas" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104 +msgid "Outputs" +msgstr "Salidas" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Input" +msgstr "agregar entrada" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Output" +msgstr "agregar salida" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Input" +msgstr "Remover punto de sincron�" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Output" +msgstr "# Salidas" + +#: gtk_ardour/io_selector.cc:144 +#, fuzzy +msgid "Disconnect All" +msgstr "Desconectar" + +#: gtk_ardour/io_selector.cc:158 +msgid "Available connections" +msgstr "Conecciones disponibles" + +#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636 +#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724 +msgid "port" +msgstr "conector" + +#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587 +msgid "There are no more JACK ports available." +msgstr "" + +#: gtk_ardour/io_selector.cc:790 +msgid "ardour: " +msgstr "" + +#: gtk_ardour/keyboard.cc:419 +msgid "KeyboardTarget: keyname \"%1\" is unknown." +msgstr "" + +#: gtk_ardour/keyboard.cc:645 +msgid "" +"Your system is completely broken - NumLock uses \"%1\"as its modifier. This " +"is madness - see the man page for xmodmap to find out how to fix this." +msgstr "" + +#: gtk_ardour/keyboard.cc:653 +msgid "" +"Your system generates \"%1\" when the NumLock key is pressed. This can cause " +"problems when editing so Ardour will use %2 to mean Meta rather than %1" +msgstr "" + +#: gtk_ardour/keyboard.cc:714 +msgid "You have %1 keys bound to \"mod1\"" +msgstr "Tiene %1 teclas asignadas a \"mod1\"" + +#: gtk_ardour/keyboard.cc:729 +msgid "You have %1 keys bound to \"mod2\"" +msgstr "Tiene %1 teclas asignadas a \"mod2\"" + +#: gtk_ardour/keyboard.cc:744 +msgid "You have %1 keys bound to \"mod3\"" +msgstr "Tiene %1 teclas asignadas a \"mod3\"" + +#: gtk_ardour/keyboard.cc:759 +msgid "You have %1 keys bound to \"mod4\"" +msgstr "Tiene %1 teclas asignadas a \"mod4\"" + +#: gtk_ardour/keyboard.cc:774 +msgid "You have %1 keys bound to \"mod5\"" +msgstr "Tiene %1 teclas asignadas a \"mod5\"" + +#: gtk_ardour/keyboard_target.cc:72 +msgid "KeyboardTarget: empty string passed to add_binding." +msgstr "" + +#: gtk_ardour/keyboard_target.cc:78 +msgid "KeyboardTarget: no translation found for \"%1\"" +msgstr "" + +#: gtk_ardour/keyboard_target.cc:83 +msgid "KeyboardTarget: unknown action \"%1\"" +msgstr "" + +#: gtk_ardour/keyboard_target.cc:248 +msgid "misformed binding node - ignored" +msgstr "" + +#: gtk_ardour/library_ui.cc:62 +msgid "Soundfile Library" +msgstr "Biblioteca de audio" + +#: gtk_ardour/library_ui.cc:63 +msgid "Filesystem" +msgstr "Explorador de archivos" + +#: gtk_ardour/library_ui.cc:66 +msgid "Split Channels" +msgstr "Separar canales" + +#: gtk_ardour/library_ui.cc:69 +msgid "ardour: soundfile selector" +msgstr "ardour: seleccin de color" + +#: gtk_ardour/library_ui.cc:430 +msgid "Add to Library..." +msgstr "Agregar a Biblioteca..." + +#: gtk_ardour/library_ui.cc:431 +msgid "Remove..." +msgstr "Quitar..." + +#: gtk_ardour/library_ui.cc:432 +msgid "Find..." +msgstr "Buscar..." + +#: gtk_ardour/library_ui.cc:433 +msgid "Add Folder" +msgstr "Agregar Carpeta" + +#: gtk_ardour/library_ui.cc:434 +msgid "Add audio file or directory" +msgstr "Agregar archivo o carpeta" + +#: gtk_ardour/library_ui.cc:713 +msgid "Importing" +msgstr "Importando" + +#: gtk_ardour/library_ui.cc:748 +msgid "%1 not added to database" +msgstr "%1 se agreg a banco de dados" + +#: gtk_ardour/library_ui.cc:767 +msgid "Folder name:" +msgstr "Nombre de carpeta:" + +#: gtk_ardour/library_ui.cc:838 +msgid "Should not be reached" +msgstr "No deber� alcanzarse" + +#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096 +msgid "file \"%1\" could not be opened" +msgstr "el archivo \"%1\" no se pudo abrir" + +#: gtk_ardour/library_ui.cc:956 +msgid "Field" +msgstr "Campo" + +#: gtk_ardour/library_ui.cc:957 +msgid "Value" +msgstr "Valor" + +#: gtk_ardour/library_ui.cc:973 +msgid "Stop" +msgstr "Detener" + +#: gtk_ardour/library_ui.cc:974 +msgid "Add Field..." +msgstr "Agregar Campo..." + +#: gtk_ardour/library_ui.cc:975 +msgid "Remove Field" +msgstr "Quitar Campo" + +#: gtk_ardour/library_ui.cc:979 +msgid "Soundfile Info" +msgstr "Informacin de archivo" + +#: gtk_ardour/library_ui.cc:1106 +msgid "file \"%1\" appears not to be an audio file" +msgstr "" + +#: gtk_ardour/library_ui.cc:1159 +#, fuzzy +msgid "Could not read file: %1 (%2)." +msgstr "No se pudo abrir el archivo \"%1\" (%2)" + +#: gtk_ardour/library_ui.cc:1177 +msgid "Could not access soundfile: " +msgstr "No se pudo acceder a archivo de audio" + +#: gtk_ardour/library_ui.cc:1222 +msgid "Field name:" +msgstr "Nombre del campo:" + +#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367 +msgid "Field value:" +msgstr "Valor del campo:" + +#: gtk_ardour/library_ui.cc:1295 +msgid "Find" +msgstr "Buscar" + +#: gtk_ardour/library_ui.cc:1296 +msgid "AND" +msgstr "Y" + +#: gtk_ardour/library_ui.cc:1297 +msgid "OR" +msgstr "O" + +#: gtk_ardour/library_ui.cc:1300 +msgid "ardour: locate soundfiles" +msgstr "ardour: localizar archivos de audio" + +#: gtk_ardour/library_ui.cc:1426 +msgid "Results" +msgstr "Resultados" + +#: gtk_ardour/library_ui.cc:1427 +msgid "Uris" +msgstr "URIs" + +#: gtk_ardour/library_ui.cc:1439 +msgid "Create multi-channel region" +msgstr "Crear regin multi canal" + +#: gtk_ardour/library_ui.cc:1442 +msgid "Ardour: Search Results" +msgstr "Ardour: Resultado de Bsqueda" + +#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50 +#, fuzzy +msgid "Set" +msgstr "Selecionar" + +#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51 +msgid "Go" +msgstr "" + +#: gtk_ardour/location_ui.cc:54 +msgid "CD" +msgstr "CD" + +#: gtk_ardour/location_ui.cc:55 +#, fuzzy +msgid "Hidden" +msgstr "Oculto" + +#: gtk_ardour/location_ui.cc:57 +msgid "SCMS" +msgstr "" + +#: gtk_ardour/location_ui.cc:58 +msgid "Pre-Emphasis" +msgstr "" + +#: gtk_ardour/location_ui.cc:592 +#, fuzzy +msgid "Add New Location" +msgstr "Agregar nueva localizacin" + +#: gtk_ardour/location_ui.cc:593 +msgid "Add New Range" +msgstr "Agregar nueva regin" + +#: gtk_ardour/location_ui.cc:597 +msgid "ardour: locations" +msgstr "ardour: localizaciones" + +#: gtk_ardour/location_ui.cc:598 +msgid "ardour_locations" +msgstr "" + +#: gtk_ardour/location_ui.cc:629 +#, fuzzy +msgid "Location (CD Index) Markers" +msgstr "Marcadores de localizacin" + +#: gtk_ardour/location_ui.cc:649 +#, fuzzy +msgid "Range (CD Track) Markers" +msgstr "Marcadores de intervalo" + +#: gtk_ardour/location_ui.cc:814 +#, fuzzy +msgid "add range marker" +msgstr "agregar un marcador de regin" + +#: gtk_ardour/main.cc:76 +msgid "ardour is killing itself for a clean exit\n" +msgstr "ardour se est�cerrando limpiamente\n" + +#: gtk_ardour/main.cc:85 +msgid "stopping user interface\n" +msgstr "deteniendo interfase visual\n" + +#: gtk_ardour/main.cc:104 +#, c-format +msgid "%d(%d): received signal %d\n" +msgstr "" + +#: gtk_ardour/main.cc:190 +msgid "cannot become new process group leader (%1)" +msgstr "" + +#: gtk_ardour/main.cc:217 +msgid "cannot setup signal handling for %1" +msgstr "" + +#: gtk_ardour/main.cc:228 +msgid "cannot set default signal mask (%1)" +msgstr "" + +#: gtk_ardour/main.cc:253 +#, fuzzy +msgid "" +"Without a UI style file, ardour will look strange.\n" +" Please set ARDOUR_UI_RC to point to a valid UI style file" +msgstr "" +"Sin un archivo de interfase visual, Ardour no se \n" +"ver�correctamente. Apunte ARDOUR_UI_RC a un archivo v�ido" + +#: gtk_ardour/main.cc:292 +#, fuzzy +msgid "" +"Ardour could not connect to JACK.\n" +"There are several possible reasons:\n" +"\n" +"1) JACK is not running.\n" +"2) JACK is running as another user, perhaps root.\n" +"3) There is already another client called \"ardour\".\n" +"\n" +"Please consider the possibilities, and perhaps (re)start JACK." +msgstr "" +"Ardour no pudo conectarse a JACK.\n" +"Hay varias razones posibles:\n" +"\n" +"1) JACK no est�corriendo.\n" +"2) JACK est�corriendo bajo otro nombre de usuario,tal vez root.\n" +"3) Ya hay otro cliente JACK corriendo con el nombre \"ardour\".\n" +"\n" +"Considere estas posibilidades y o reinicie a JACK.\n" + +#: gtk_ardour/main.cc:305 +#, fuzzy +msgid "ardour: unplugged" +msgstr "ardour: desconectado" + +#: gtk_ardour/main.cc:363 +msgid "Ardour/GTK " +msgstr "" + +#: gtk_ardour/main.cc:365 +msgid "" +"\n" +" (built using " +msgstr "" + +#: gtk_ardour/main.cc:369 +#, fuzzy +msgid " with libardour " +msgstr " corriendo con libardour " + +#: gtk_ardour/main.cc:374 +msgid " and GCC version " +msgstr "" + +#: gtk_ardour/main.cc:384 +msgid "Copyright (C) 1999-2005 Paul Davis" +msgstr "" + +#: gtk_ardour/main.cc:385 +msgid "" +"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel " +"Baker" +msgstr "" + +#: gtk_ardour/main.cc:387 +msgid "Ardour comes with ABSOLUTELY NO WARRANTY" +msgstr "Ardour no ofrece ningn tipo de garant�" + +#: gtk_ardour/main.cc:388 +msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +msgstr "" + +#: gtk_ardour/main.cc:389 +msgid "This is free software, and you are welcome to redistribute it " +msgstr "Este software es gratuito.Usted puede distribuirlo " + +#: gtk_ardour/main.cc:390 +#, fuzzy +msgid "under certain conditions; see the source for copying conditions." +msgstr "bajo ciertas condiciones; lea el archivo COPYING para m� detalles" + +#: gtk_ardour/main.cc:399 +msgid "could not create ARDOUR GUI" +msgstr "no se pudo crear la interfase visual de Ardour" + +#: gtk_ardour/main.cc:419 +msgid "Could not connect to JACK server as \"%1\"" +msgstr "No se pudo conectar a JACK con el nombre \"%1\"" + +#: gtk_ardour/main.cc:424 +msgid "could not initialize Ardour." +msgstr "no se pudo iniciar a Ardour." + +#: gtk_ardour/main.cc:435 +msgid "could not load command line session \"%1\"" +msgstr "no se pudo cargar desde l�ea de comando a la sesin \"%1\"" + +#: gtk_ardour/main.cc:455 +msgid "" +"\n" +"\n" +"A session named \"%1\" already exists.\n" +"To avoid this message, start ardour as \"ardour %1" +msgstr "" + +#: gtk_ardour/main.cc:466 +msgid "" +"\n" +"\n" +"No session named \"%1\" exists.\n" +"To create it from the command line, start ardour as \"ardour --new %1" +msgstr "" + +#: gtk_ardour/marker.cc:354 +#, fuzzy +msgid "MarkerText" +msgstr "Marcas" + +#: gtk_ardour/marker_time_axis.cc:271 +#, fuzzy +msgid "Remove Marker" +msgstr "quitar marcador" + +#: gtk_ardour/marker_time_axis.cc:273 +#, fuzzy +msgid "Marker" +msgstr "Marcas" + +#: gtk_ardour/meter_bridge.cc:74 +msgid "ardour: meter bridge" +msgstr "ardour: vmetro" + +#: gtk_ardour/meter_bridge.cc:75 +msgid "ardour_meter_bridge" +msgstr "" + +#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93 +#, c-format +msgid "# of %u-sample overs" +msgstr "" + +#: gtk_ardour/meter_bridge_strip.cc:219 +msgid "New name for meter:" +msgstr "Nuevo nombre para vmetro" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507 +#: gtk_ardour/region_editor.cc:45 +msgid "mute" +msgstr "mudo" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508 +msgid "solo" +msgstr "solo" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506 +msgid "RECORD" +msgstr "GRABAR" + +#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514 +msgid "polarity" +msgstr "polaridad" + +#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509 +msgid "comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810 +msgid "INPUT" +msgstr "ENTRADA" + +#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831 +msgid "OUTPUT" +msgstr "SALIDA" + +#: gtk_ardour/mixer_strip.cc:173 +#, fuzzy +msgid "Pan automation mode" +msgstr "modo de automatizacin de balance" + +#: gtk_ardour/mixer_strip.cc:174 +#, fuzzy +msgid "Gain automation mode" +msgstr "modo de automatizacin de volumen" + +#: gtk_ardour/mixer_strip.cc:176 +#, fuzzy +msgid "Pan automation type" +msgstr "estado de automatizacin de balance" + +#: gtk_ardour/mixer_strip.cc:177 +#, fuzzy +msgid "Gain automation type" +msgstr "estado de automatizacin de volumen" + +#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232 +#: gtk_ardour/mixer_strip.cc:979 +#, fuzzy +msgid "trim" +msgstr "cortar" + +#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233 +#: gtk_ardour/mixer_strip.cc:983 +msgid "abs" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:240 +#, fuzzy +msgid "gain automation mode" +msgstr "modo de automatizacin de volumen" + +#: gtk_ardour/mixer_strip.cc:241 +#, fuzzy +msgid "pan automation mode" +msgstr "modo de automatizacin de balance" + +#: gtk_ardour/mixer_strip.cc:242 +#, fuzzy +msgid "gain automation state" +msgstr "estado de automatizacin de volumen" + +#: gtk_ardour/mixer_strip.cc:243 +#, fuzzy +msgid "pan automation state" +msgstr "estado de automatizacin de balance" + +#: gtk_ardour/mixer_strip.cc:259 +msgid "varispeed" +msgstr "velocidad" + +#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174 +msgid "click to add/edit comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:463 +msgid "unknown strip width \"%1\" in XML GUI information" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:522 +msgid "REC" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:525 +#, fuzzy +msgid "cmt" +msgstr "cortar" + +#: gtk_ardour/mixer_strip.cc:530 +msgid "pol" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620 +#: gtk_ardour/redirect_box.cc:1180 +msgid "Not connected to JACK - no I/O changes are possible" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667 +msgid "could not register new ports required for that connection" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:813 +msgid "IN" +msgstr "ENTRADA" + +#: gtk_ardour/mixer_strip.cc:834 +msgid "OUT" +msgstr "SALIDA" + +#: gtk_ardour/mixer_strip.cc:950 +msgid "aplay" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:956 +msgid "awrite" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:1134 +#, fuzzy +msgid ": comment editor" +msgstr "no se pudo iniciar el editor" + +#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224 +msgid "no group" +msgstr "sin grupo" + +#: gtk_ardour/mixer_strip.cc:1227 +msgid "~G" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:52 +msgid "Strips" +msgstr "Pistas" + +#: gtk_ardour/mixer_ui.cc:56 +msgid "Snapshots" +msgstr "Capturas" + +#: gtk_ardour/mixer_ui.cc:61 +msgid "***" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17 +#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144 +#: gtk_ardour/tempo_dialog.cc:162 +msgid "Bar" +msgstr "Comp�" + +#: gtk_ardour/mixer_ui.cc:121 +msgid "Mix Groups" +msgstr "Grupos de Mixer" + +#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373 +msgid "ardour: mixer" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:192 +msgid "ardour_mixer" +msgstr "ardour_mixer" + +#: gtk_ardour/mixer_ui.cc:342 +msgid "ardour: mixer: " +msgstr "" + +#: gtk_ardour/mixer_ui.cc:641 +msgid "signal" +msgstr "seal" + +#: gtk_ardour/mixer_ui.cc:672 +msgid "Show All AudioTrack MixerStrips" +msgstr "Mostrar todas las pistas de Audio en el Mixer" + +#: gtk_ardour/mixer_ui.cc:673 +msgid "Hide All AudioTrack MixerStrips" +msgstr "Ocultar todas las pistas de Audio en el Mixer" + +#: gtk_ardour/mixer_ui.cc:674 +msgid "Show All AudioBus MixerStrips" +msgstr "Mostrar todos los Buses en el Mixer" + +#: gtk_ardour/mixer_ui.cc:675 +msgid "Hide All AudioBus MixerStrips" +msgstr "Ocultar todos los Buses en el Mixer" + +#: gtk_ardour/mixer_ui.cc:687 +msgid "track display list item for renamed strip not found!" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:700 +msgid "Name for new mix group" +msgstr "Nombre para nuevo grupo del mixer" + +# +#: gtk_ardour/new_session_dialog.cc:39 +#, fuzzy +msgid "Session name:" +msgstr "Nombre de sesin:" + +#: gtk_ardour/new_session_dialog.cc:39 +#, fuzzy +msgid "Create" +msgstr "Crear" + +#: gtk_ardour/new_session_dialog.cc:40 +#, fuzzy +msgid "use control outs" +msgstr "Usar salidas de Control" + +#: gtk_ardour/new_session_dialog.cc:41 +#, fuzzy +msgid "use master outs" +msgstr "usar salidas Master" + +#: gtk_ardour/new_session_dialog.cc:42 +#, fuzzy +msgid "automatically connect track inputs to physical ports" +msgstr "conectar autom�icamente entradas de pistas a entradas f�icas" + +#: gtk_ardour/new_session_dialog.cc:43 +#, fuzzy +msgid "automatically connect track outputs to master outs" +msgstr "conectar autom�icamente salidas de pistas a salidas Master" + +#: gtk_ardour/new_session_dialog.cc:44 +#, fuzzy +msgid "automatically connect track outputs to physical ports" +msgstr "conectar autom�icamente salidas de pistas a salidas f�icas" + +#: gtk_ardour/new_session_dialog.cc:45 +msgid "manually connect track outputs" +msgstr "conectar pistas manualmente" + +#: gtk_ardour/new_session_dialog.cc:50 +#, fuzzy +msgid "Advanced..." +msgstr "Avanzado..." + +#: gtk_ardour/new_session_dialog.cc:52 +#, fuzzy +msgid "show again" +msgstr "Mostrar toda automatizacin" + +#: gtk_ardour/new_session_dialog.cc:55 +msgid "Hardware Inputs: use" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:56 +msgid "Hardware Outputs: use" +msgstr "" + +# +#: gtk_ardour/new_session_dialog.cc:62 +#, fuzzy +msgid "new session setup" +msgstr "Configuracin para nueva sesin" + +#: gtk_ardour/new_session_dialog.cc:63 +msgid "ardour_new_session" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:72 +msgid "This session will playback and record at %1 Hz" +msgstr "Esta sesin reproducir�y grabar�a %1 Hz" + +#: gtk_ardour/new_session_dialog.cc:74 +#, fuzzy +msgid "" +"This rate is set by JACK and cannot be changed.\n" +"If you want to use a different sample rate\n" +"please exit and restart JACK" +msgstr "" +"Esta frecuencia de muestreo es configurada por JACK\n" +"y no puede ser modificada desde Ardour.Si desea una\n" +"frecuencia de muestreo distinta, cierre Ardour,reinice\n" +"JACK y vuelva a ejecutar Ardour\n" + +#: gtk_ardour/new_session_dialog.cc:155 +#, fuzzy +msgid "Session template" +msgstr "usar esquema existente" + +#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20 +#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146 +#: gtk_ardour/tempo_dialog.cc:164 +msgid "Location" +msgstr "Localizacin" + +#: gtk_ardour/new_session_dialog.cc:178 +msgid "Configuration" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:269 +msgid "blank" +msgstr "en blanco" + +#: gtk_ardour/new_session_dialog.cc:328 +msgid "No template - create tracks/busses manually" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:337 +#, fuzzy +msgid "No template" +msgstr "-esquema" + +#: gtk_ardour/option_editor.cc:48 +#, fuzzy +msgid "Internal" +msgstr "interno" + +#: gtk_ardour/option_editor.cc:49 +#, fuzzy +msgid "Slave to MTC" +msgstr "Enviar MTC" + +#: gtk_ardour/option_editor.cc:50 +msgid "Sync with JACK" +msgstr "" + +#: gtk_ardour/option_editor.cc:51 +msgid "never used but stops crashes" +msgstr "" + +#: gtk_ardour/option_editor.cc:56 +#, fuzzy +msgid "Later regions are higher" +msgstr "Bajar regin una capa" + +#: gtk_ardour/option_editor.cc:57 +msgid "Most recently added/moved/trimmed regions are higher" +msgstr "" + +#: gtk_ardour/option_editor.cc:58 +#, fuzzy +msgid "Most recently added regions are higher" +msgstr "Bajar regin una capa" + +#: gtk_ardour/option_editor.cc:63 +#, fuzzy +msgid "Span entire region overlap" +msgstr "Elevar regin una capa" + +#: gtk_ardour/option_editor.cc:64 +msgid "Short fades at the start of the overlap" +msgstr "" + +#: gtk_ardour/option_editor.cc:82 +#, fuzzy +msgid "Automatically create crossfades" +msgstr "Crosfade autom�ico si dos regiones se superponen" + +#: gtk_ardour/option_editor.cc:83 +msgid "New full-overlap crossfades are unmuted" +msgstr "" + +#: gtk_ardour/option_editor.cc:84 +#, fuzzy +msgid "Region layering mode" +msgstr "Fines de regin" + +#: gtk_ardour/option_editor.cc:85 +#, fuzzy +msgid "Crossfade model" +msgstr "editar fade in" + +#: gtk_ardour/option_editor.cc:90 +msgid "Latched solo" +msgstr "" + +#: gtk_ardour/option_editor.cc:91 +msgid "Solo via bus" +msgstr "" + +#: gtk_ardour/option_editor.cc:96 +#, fuzzy +msgid "Show waveforms while recording" +msgstr "Mostrar onda de audio" + +#: gtk_ardour/option_editor.cc:97 +msgid "Narrow mixer strips" +msgstr "Estrechar pistas del mixer" + +#: gtk_ardour/option_editor.cc:98 +msgid "Show measure lines" +msgstr "Mostrar l�eas de medida" + +#: gtk_ardour/option_editor.cc:99 +msgid "Follow playhead" +msgstr "Seguir a la barra de reproduccin" + +#: gtk_ardour/option_editor.cc:103 +msgid "Send MTC" +msgstr "Enviar MTC" + +#: gtk_ardour/option_editor.cc:104 +msgid "Send MMC" +msgstr "Enviar MMC" + +#: gtk_ardour/option_editor.cc:105 +msgid "JACK time master" +msgstr "M�ter de tiempo JACK" + +#: gtk_ardour/option_editor.cc:107 +msgid "SMPTE offset is negative" +msgstr "" + +#: gtk_ardour/option_editor.cc:111 +msgid "Send MIDI parameter feedback" +msgstr "" + +#: gtk_ardour/option_editor.cc:112 +msgid "MIDI parameter control" +msgstr "" + +#: gtk_ardour/option_editor.cc:113 +#, fuzzy +msgid "MMC control" +msgstr "Puerto MMC" + +#: gtk_ardour/option_editor.cc:131 +#, fuzzy +msgid "Auto-connect new track inputs to hardware" +msgstr "Conectar nuevas pistas autom�icamente" + +#: gtk_ardour/option_editor.cc:132 +#, fuzzy +msgid "Auto-connect new track outputs to hardware" +msgstr "Conectar nuevas pistas autom�icamente" + +#: gtk_ardour/option_editor.cc:133 +#, fuzzy +msgid "Auto-connect new track outputs to master bus" +msgstr "conectar autom�icamente salidas de pistas a salidas Master" + +#: gtk_ardour/option_editor.cc:134 +#, fuzzy +msgid "Manually connect new track outputs" +msgstr "conectar pistas manualmente" + +#: gtk_ardour/option_editor.cc:135 +msgid "Use Hardware Monitoring" +msgstr "Monitorizacin por Hardware" + +#: gtk_ardour/option_editor.cc:136 +msgid "Use Software Monitoring" +msgstr "Monitorizacin por Software" + +#: gtk_ardour/option_editor.cc:137 +msgid "Stop plugins with transport" +msgstr "No procesar plugins durante transporte" + +#: gtk_ardour/option_editor.cc:138 +msgid "Run plugins while recording" +msgstr "Procesar plugins durante la grabacin" + +#: gtk_ardour/option_editor.cc:139 +#, fuzzy +msgid "Verify remove last capture" +msgstr "Quitar ltima captura" + +#: gtk_ardour/option_editor.cc:140 +msgid "Stop recording on xrun" +msgstr "Detener grabacin al detectar un XRUN" + +#: gtk_ardour/option_editor.cc:141 +msgid "Stop transport at end of session" +msgstr "Detener el transporte al llegar al final de la sesin" + +#: gtk_ardour/option_editor.cc:142 +msgid "Debug keyboard events" +msgstr "" + +#: gtk_ardour/option_editor.cc:143 +msgid "-12dB gain reduction for ffwd/rew" +msgstr "" + +#: gtk_ardour/option_editor.cc:152 +msgid "ardour: options editor" +msgstr "ardour: opciones editor" + +#: gtk_ardour/option_editor.cc:153 +msgid "ardour_option_editor" +msgstr "" + +#: gtk_ardour/option_editor.cc:183 +msgid "Misc" +msgstr "Miscel�ea" + +#: gtk_ardour/option_editor.cc:184 +msgid "Sync" +msgstr "Sincronizacin" + +#: gtk_ardour/option_editor.cc:185 +msgid "Paths/Files" +msgstr "Carpetas/Archivos" + +#: gtk_ardour/option_editor.cc:186 +msgid "Display" +msgstr "" + +#: gtk_ardour/option_editor.cc:187 +msgid "Kbd/Mouse" +msgstr "Teclado/Mouse" + +#: gtk_ardour/option_editor.cc:188 +msgid "Click" +msgstr "Metrnomo" + +#: gtk_ardour/option_editor.cc:190 +msgid "Layers & Fades" +msgstr "" + +#: gtk_ardour/option_editor.cc:195 +msgid "MIDI" +msgstr "MIDI" + +#: gtk_ardour/option_editor.cc:268 +msgid "24 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:270 +msgid "25 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:272 +msgid "30 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:278 +msgid "30 FPS drop" +msgstr "" + +#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379 +#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736 +#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800 +msgid "Medium" +msgstr "" + +#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738 +#: gtk_ardour/option_editor.cc:804 +#, fuzzy +msgid "Faster" +msgstr "Fades" + +#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714 +#: gtk_ardour/option_editor.cc:776 +#, fuzzy +msgid "Short" +msgstr "conector" + +#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716 +#: gtk_ardour/option_editor.cc:780 +msgid "Long" +msgstr "" + +#: gtk_ardour/option_editor.cc:396 +msgid "Broadcast WAVE/floating point" +msgstr "Broadcast WAVE/punto flotante" + +#: gtk_ardour/option_editor.cc:397 +msgid "WAVE/floating point" +msgstr "WAVE/punto flotante" + +#: gtk_ardour/option_editor.cc:417 +msgid "session RAID path" +msgstr "ubicacin de archivos de sesin" + +#: gtk_ardour/option_editor.cc:422 +msgid "Native Format" +msgstr "Formato Nativo" + +#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460 +#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409 +msgid "internal" +msgstr "interno" + +#: gtk_ardour/option_editor.cc:537 +msgid "Short crossfade length (msecs)" +msgstr "" + +#: gtk_ardour/option_editor.cc:710 +msgid "Meter Peak Hold" +msgstr "" + +#: gtk_ardour/option_editor.cc:730 +msgid "Meter Falloff" +msgstr "" + +#: gtk_ardour/option_editor.cc:847 +msgid "Positional Sync" +msgstr "" + +#: gtk_ardour/option_editor.cc:902 +msgid "SMPTE Frames/second" +msgstr "SMPTE Cuadros/segundo" + +#: gtk_ardour/option_editor.cc:903 +msgid "SMPTE Offset" +msgstr "" + +#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013 +#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211 +#, fuzzy +msgid "online" +msgstr "linear" + +#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014 +#: gtk_ardour/option_editor.cc:1208 +#, fuzzy +msgid "offline" +msgstr "linear" + +#: gtk_ardour/option_editor.cc:1319 +msgid "Use as click" +msgstr "Usar como metrnomo" + +#: gtk_ardour/option_editor.cc:1344 +msgid "Use as click emphasis" +msgstr "Usar como �fasis de metrnomo" + +#: gtk_ardour/option_editor.cc:1478 +msgid "--unknown--" +msgstr "--desconocido--" + +#: gtk_ardour/option_editor.cc:1595 +msgid "Click audio file" +msgstr "Archivo de sonido para metrnomo" + +#: gtk_ardour/option_editor.cc:1601 +msgid "Click emphasis audiofile" +msgstr "Archivo de sonido de �fasis de metrnomo" + +#: gtk_ardour/option_editor.cc:1638 +msgid "" +"The auditioner is a dedicated mixer strip used\n" +"for listening to specific regions outside the context\n" +"of the overall mix. It can be connected just like any\n" +"other mixer strip." +msgstr "" +"El audicionador es una salida de sonido dedicada empleada\n" +"para o� regiones espec�icas de la sesin o para\n" +"escuchar archivos de sonido en el men Biblioteca de Audio\n" +"Se puede configurar sus conecciones como a cualquier.otra del mixer" + +#: gtk_ardour/option_editor.cc:1887 +msgid "Edit using" +msgstr "Editar con" + +#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924 +msgid "+ button" +msgstr "botn +" + +#: gtk_ardour/option_editor.cc:1917 +msgid "Delete using" +msgstr "Eliminar con" + +#: gtk_ardour/option_editor.cc:1947 +msgid "Ignore snap using" +msgstr "Ignorar trabar con" + +#: gtk_ardour/opts.cc:46 +msgid "Usage: " +msgstr "Uso: " + +#: gtk_ardour/opts.cc:47 +msgid " -v, --version Show version information\n" +msgstr "" +" -v, --version Mostra informacin acerca de la versin\n" + +#: gtk_ardour/opts.cc:48 +msgid " -h, --help Print this message\n" +msgstr " -h, --help Muestra este mensage\n" + +#: gtk_ardour/opts.cc:49 +msgid "" +" -b, --bindings Print all possible keyboard binding " +"names\n" +msgstr "" +" -b, --bindings Muestra todos los comandos asignables a " +"botones del teclado(shortcuts)\n" + +#: gtk_ardour/opts.cc:50 +#, fuzzy +msgid " -n, --show-splash Show splash screen\n" +msgstr " -n, --no-splash No mostrar recuadro inicial\n" + +#: gtk_ardour/opts.cc:51 +#, fuzzy +msgid "" +" -c, --name name Use a specific jack client name, default " +"is ardour\n" +msgstr "" +" -c, --jack-client-name nombre Nombre de cliente jack para Ardour. Si " +"no selecciona ninguno, el nombre ser�ardour\n" + +#: gtk_ardour/opts.cc:52 +#, fuzzy +msgid "" +" -N, --new session-name Create a new session from the command " +"line\n" +msgstr " [nombre-sesin] Nombre de sesin a cargar\n" + +#: gtk_ardour/opts.cc:53 +msgid "" +" -o, --use-hw-optimizations Try to use h/w specific optimizations\n" +msgstr "" + +#: gtk_ardour/opts.cc:55 +#, fuzzy +msgid " -V, --novst Do not use VST support\n" +msgstr " -n, --no-splash No mostrar recuadro inicial\n" + +#: gtk_ardour/opts.cc:57 +msgid " [session-name] Name of session to load\n" +msgstr " [nombre-sesin] Nombre de sesin a cargar\n" + +#: gtk_ardour/opts.cc:58 +msgid " -C, --curvetest filename Curve algorithm debugger\n" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:58 +msgid "You can't graphically edit panning of more than stream" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:78 +#, fuzzy +msgid "add pan automation event" +msgstr "agregar evento de automatizacin a " + +#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441 +#, fuzzy +msgid "Bypass" +msgstr "no procesar" + +#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222 +#, fuzzy +msgid "link" +msgstr "entrada" + +#: gtk_ardour/panner_ui.cc:103 +msgid "panning link control" +msgstr "" + +#: gtk_ardour/panner_ui.cc:105 +msgid "panning link direction" +msgstr "" + +#: gtk_ardour/panner_ui.cc:232 +msgid "L" +msgstr "" + +#: gtk_ardour/panner_ui.cc:344 +#, c-format +msgid "panner for channel %u" +msgstr "" + +#: gtk_ardour/panner_ui.cc:451 +#, fuzzy +msgid "Reset all" +msgstr "resetear" + +#: gtk_ardour/playlist_selector.cc:46 +msgid "Playlists grouped by track" +msgstr "" + +#: gtk_ardour/playlist_selector.cc:53 +#, fuzzy +msgid "close" +msgstr "Cerrar" + +#: gtk_ardour/playlist_selector.cc:59 +#, fuzzy +msgid "ardour: playlists" +msgstr "ardour: plugins" + +#: gtk_ardour/playlist_selector.cc:104 +#, fuzzy +msgid "ardour: playlist for " +msgstr "ardour: plugins" + +#: gtk_ardour/playlist_selector.cc:122 +#, fuzzy +msgid "Other tracks" +msgstr "Ocultar esta pista" + +#: gtk_ardour/playlist_selector.cc:138 +msgid "unassigned" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:41 +msgid "Available LADSPA plugins" +msgstr "Plugins LADSPA dispon�les" + +#: gtk_ardour/plugin_selector.cc:42 +msgid "Type" +msgstr "Tipo" + +#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51 +msgid "# Inputs" +msgstr "# Entradas" + +#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52 +msgid "# Outputs" +msgstr "# Salidas" + +#: gtk_ardour/plugin_selector.cc:50 +#, fuzzy +msgid "Available VST plugins" +msgstr "Plugins LADSPA dispon�les" + +#: gtk_ardour/plugin_selector.cc:58 +msgid "To be added" +msgstr "Plugins que se agregar�" + +#: gtk_ardour/plugin_selector.cc:72 +msgid "ardour: plugins" +msgstr "ardour: plugins" + +#: gtk_ardour/plugin_selector.cc:82 +msgid "Add a plugin to the effect list" +msgstr "Agregar plugin a lista de efectos" + +#: gtk_ardour/plugin_selector.cc:84 +msgid "Remove a plugin from the effect list" +msgstr "Quitar plugin de lista de efectos" + +#: gtk_ardour/plugin_selector.cc:88 +msgid "Update" +msgstr "Actualizar" + +#: gtk_ardour/plugin_selector.cc:89 +msgid "Update available plugins" +msgstr "Actualizar plugins dispon�les" + +#: gtk_ardour/plugin_selector.cc:110 +msgid "LADSPA" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:113 +msgid "VST" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:83 +msgid "" +"unknown type of editor-supplying plugin (note: no VST support in this " +"version of ardour)" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:269 +msgid "Plugin Editor: could not build control element for port %1" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "in" +msgstr "entrada" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "ins" +msgstr "entradas" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "out" +msgstr "salida" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "outs" +msgstr "salidas" + +#: gtk_ardour/plugin_ui.cc:382 +#, fuzzy +msgid "automation control" +msgstr "mover evento de automatizacin" + +#: gtk_ardour/plugin_ui.cc:869 +#, fuzzy +msgid "save" +msgstr "Guardar" + +#: gtk_ardour/plugin_ui.cc:870 +msgid "bypass" +msgstr "no procesar" + +#: gtk_ardour/plugin_ui.cc:892 +msgid "Plugin preset %1 not found" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:903 +msgid "Name for plugin settings:" +msgstr "Nombre para configuracin de plugin" + +#: gtk_ardour/redirect_automation_line.cc:53 +msgid "redirect automation created for non-plugin" +msgstr "automatizacin creada para un redireccionamiento no-plugin" + +#: gtk_ardour/redirect_automation_time_axis.cc:92 +#, fuzzy +msgid "add automation event to " +msgstr "agregar evento de automatizacin a " + +#: gtk_ardour/redirect_box.cc:213 +msgid "New send" +msgstr "" + +#: gtk_ardour/redirect_box.cc:214 +#, fuzzy +msgid "Show send controls" +msgstr "Control de velocidad y sentido de reproduccin(pitch)" + +#: gtk_ardour/redirect_box.cc:360 +msgid "New Plugin ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:361 +#, fuzzy +msgid "New Insert" +msgstr "nueva entrada" + +#: gtk_ardour/redirect_box.cc:362 +msgid "New Send ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:380 +#, fuzzy +msgid "Select all" +msgstr "Seleccionar todo" + +#: gtk_ardour/redirect_box.cc:381 +#, fuzzy +msgid "Deselect all" +msgstr "Seleccionar todo" + +#: gtk_ardour/redirect_box.cc:389 +#, fuzzy +msgid "Inserts" +msgstr "Invertir" + +#: gtk_ardour/redirect_box.cc:390 +#, fuzzy +msgid "Sends" +msgstr "Minutos:Segundos" + +#: gtk_ardour/redirect_box.cc:393 +#, fuzzy +msgid "Select all ..." +msgstr "Seleccionar todo" + +#: gtk_ardour/redirect_box.cc:406 +#, fuzzy +msgid "Activate All" +msgstr "Activar" + +#: gtk_ardour/redirect_box.cc:407 +#, fuzzy +msgid "Deactivate All" +msgstr "Desactivar" + +#: gtk_ardour/redirect_box.cc:488 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point, there are\n" +"%3 active signal streams.\n" +"\n" +"This makes no sense - you are throwing away\n" +"part of the signal." +msgstr "" + +#: gtk_ardour/redirect_box.cc:500 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point there are\n" +"only %3 active signal streams.\n" +"\n" +"This makes no sense - unless the plugin supports\n" +"side-chain inputs. A future version of Ardour will\n" +"support this type of configuration." +msgstr "" + +#: gtk_ardour/redirect_box.cc:513 +msgid "" +"You attempted to add a plugin (%1).\n" +"\n" +"The I/O configuration doesn't make sense:\n" +"\n" +"The plugin has %2 inputs and %3 outputs.\n" +"The track/bus has %4 inputs and %5 outputs.\n" +"The insertion point, has %6 active signals.\n" +"\n" +"Ardour does not understand what to do in such situations.\n" +msgstr "" + +#: gtk_ardour/redirect_box.cc:616 +msgid "Pre-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:619 +msgid "Post-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:781 +msgid "" +"You cannot reorder this set of redirects\n" +"in that way because the inputs and\n" +"outputs do not work correctly." +msgstr "" + +#: gtk_ardour/redirect_box.cc:903 +#, fuzzy +msgid "ardour: rename redirect" +msgstr "ardour: renombrar regin" + +#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043 +msgid "" +"Copying the set of redirects on the clipboard failed,\n" +"probably because the I/O configuration of the plugins\n" +"could not match the configuration of this track." +msgstr "" + +#: gtk_ardour/redirect_box.cc:1064 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this track?\n" +"(this cannot be undone)" +msgstr "" +"Realmente desea quitar la pista \"%1\" ?\n" +"(no podr�deshacer esto)" + +#: gtk_ardour/redirect_box.cc:1067 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this bus?\n" +"(this cannot be undone)" +msgstr "" +"Realmente desea quitar la pista \"%1\" ?\n" +"(no podr�deshacer esto)" + +#: gtk_ardour/redirect_box.cc:1071 +#, fuzzy +msgid "Yes, remove them all" +msgstr "Si, eliminar esto." + +#: gtk_ardour/redirect_box.cc:1114 +#, fuzzy +msgid "ardour: %1" +msgstr "ardour: reloj" + +#: gtk_ardour/redirect_box.cc:1156 +#, fuzzy +msgid "ardour: %1: %2 (by %3)" +msgstr "ardour: regin" + +#: gtk_ardour/region_editor.cc:43 +msgid "NAME:" +msgstr "NOMBRE:" + +#: gtk_ardour/region_editor.cc:44 +msgid "lock" +msgstr "bloquear" + +#: gtk_ardour/region_editor.cc:46 +msgid "opaque" +msgstr "opaco" + +#: gtk_ardour/region_editor.cc:49 +msgid "Layer" +msgstr "Capa" + +#: gtk_ardour/region_editor.cc:57 +msgid "ENVELOPE" +msgstr "ENVELOPE" + +#: gtk_ardour/region_editor.cc:108 +msgid "mute this region" +msgstr "enmudecer a esta regin" + +#: gtk_ardour/region_editor.cc:109 +msgid "regions underneath this one cannot be heard" +msgstr "no se oir� a las regiones que est� bajo �ta" + +#: gtk_ardour/region_editor.cc:110 +msgid "prevent any changes to this region" +msgstr "bloquear contra cambios a esta regin" + +#: gtk_ardour/region_editor.cc:111 +msgid "use the gain envelope during playback" +msgstr "usar envelope de volumen durante la reproduccin" + +#: gtk_ardour/region_editor.cc:112 +msgid "show the gain envelope" +msgstr "mostrar envelope de volumen" + +#: gtk_ardour/region_editor.cc:113 +msgid "use fade in curve during playback" +msgstr "usar fade-in durante reproduccin" + +#: gtk_ardour/region_editor.cc:114 +msgid "use fade out curve during playback" +msgstr "usar fade-out durante reproduccin" + +#: gtk_ardour/region_editor.cc:115 +msgid "audition this region" +msgstr "audicionar esta regin" + +#: gtk_ardour/region_editor.cc:148 +msgid "START:" +msgstr "INICIO" + +#: gtk_ardour/region_editor.cc:150 +msgid "END:" +msgstr "FINAL:" + +#: gtk_ardour/region_editor.cc:152 +msgid "LENGTH:" +msgstr "DURACI�:" + +#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198 +#: gtk_ardour/region_editor.cc:234 +msgid "active" +msgstr "activo" + +#: gtk_ardour/region_editor.cc:179 +msgid "visible" +msgstr "visible" + +#: gtk_ardour/region_editor.cc:197 +msgid "FADE IN" +msgstr "FADE IN" + +#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235 +msgid "msecs" +msgstr "milisecs." + +#: gtk_ardour/region_editor.cc:233 +msgid "FADE OUT" +msgstr "FADE OUT" + +#: gtk_ardour/region_editor.cc:276 +msgid "ardour: region " +msgstr "ardour: regin" + +#: gtk_ardour/region_editor.cc:410 +msgid "fade in edit" +msgstr "editar fade in" + +#: gtk_ardour/region_editor.cc:422 +#, fuzzy +msgid "fade out edit" +msgstr "agregar salida" + +#: gtk_ardour/regionview.cc:1169 +#, fuzzy +msgid "add gain control point" +msgstr "Remover punto de sincron�" + +#: gtk_ardour/route_params_ui.cc:58 +msgid "Tracks/Buses" +msgstr "Pistas/Buses" + +#: gtk_ardour/route_params_ui.cc:59 +msgid "Pre Redirects" +msgstr "Pre Redireccionamentos" + +#: gtk_ardour/route_params_ui.cc:60 +msgid "Post Redirects" +msgstr "Pst Redireccionamentos" + +#: gtk_ardour/route_params_ui.cc:105 +#, fuzzy +msgid "Pre-fader Redirects" +msgstr "Pre Redireccionamentos" + +#: gtk_ardour/route_params_ui.cc:106 +#, fuzzy +msgid "Post-fader Redirects" +msgstr "Pst Redireccionamentos" + +#: gtk_ardour/route_params_ui.cc:138 +#, fuzzy +msgid "ardour: track/bus inspector" +msgstr "ardour: agregar Pistas/bus" + +#: gtk_ardour/route_params_ui.cc:139 +msgid "ardour_route_parameters" +msgstr "ardour_route_parameters" + +#: gtk_ardour/route_params_ui.cc:189 +msgid "route display list item for renamed route not found!" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:448 +msgid "NO TRACK" +msgstr "NINGUNA PISTA" + +#: gtk_ardour/route_params_ui.cc:669 +#, fuzzy +msgid "ardour: track/bus inspector: " +msgstr "ardour: agregar Pistas/bus" + +#: gtk_ardour/route_params_ui.cc:673 +msgid "No Route Selected" +msgstr "No seleccion ninguna Ruta" + +#: gtk_ardour/route_params_ui.cc:674 +#, fuzzy +msgid "ardour: track/bus/inspector: no route selected" +msgstr "ardour: par�etros de ruteo: no seleccion ninguna ruta" + +#: gtk_ardour/route_ui.cc:134 +#, fuzzy +msgid "mute change" +msgstr "Seleccionar intervalo de punch" + +#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220 +#, fuzzy +msgid "solo change" +msgstr "rango de reproduccin cont�ua" + +#: gtk_ardour/route_ui.cc:284 +msgid "rec-enable change" +msgstr "" + +#: gtk_ardour/route_ui.cc:423 +#, fuzzy +msgid "Solo-safe" +msgstr "Solo" + +#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474 +#, fuzzy +msgid "MIDI Bind" +msgstr "MIDI" + +#: gtk_ardour/route_ui.cc:445 +msgid "Pre Fader" +msgstr "Pre-Fader" + +#: gtk_ardour/route_ui.cc:452 +msgid "Post Fader" +msgstr "Pst-Fader" + +#: gtk_ardour/route_ui.cc:459 +msgid "Control Outs" +msgstr "Control de Salidas" + +#: gtk_ardour/route_ui.cc:466 +msgid "Main Outs" +msgstr "Salidas Principales" + +#: gtk_ardour/route_ui.cc:503 +msgid "mix group solo change" +msgstr "" + +#: gtk_ardour/route_ui.cc:537 +msgid "mix group mute change" +msgstr "" + +#: gtk_ardour/route_ui.cc:553 +msgid "mix group rec-enable change" +msgstr "" + +#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258 +msgid "ardour: color selection" +msgstr "ardour: seleccin de color" + +#: gtk_ardour/route_ui.cc:652 +#, fuzzy +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"You may also lose the playlist used by this track.\n" +"(cannot be undone)" +msgstr "" +"Realmente desea quitar la pista \"%1\" ?\n" +"(no podr�deshacer esto)" + +#: gtk_ardour/route_ui.cc:654 +msgid "" +"Do you really want to remove bus \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Realmente desea quitar el bus \"%1\" ?\n" +"(no podr�deshacer esto)" + +#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299 +msgid "Yes, remove it." +msgstr "Si, eliminar esto." + +#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358 +msgid "new name: " +msgstr "nuevo nombre: " + +#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31 +msgid "Beats per minute" +msgstr "Pulsos por minuto" + +#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35 +#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163 +msgid "Beat" +msgstr "Pulsos" + +#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158 +msgid "Meter denominator" +msgstr "Denominador m�rico" + +#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159 +msgid "Beats per bar" +msgstr "Pulsos por compaces" + +#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189 +msgid "whole (1)" +msgstr "toda (1)" + +#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191 +msgid "second (2)" +msgstr "segunda (2)" + +#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193 +msgid "third (3)" +msgstr "tercera (3)" + +#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195 +#: gtk_ardour/tempo_dialog.cc:203 +msgid "quarter (4)" +msgstr "cuarta (4)" + +#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197 +msgid "eighth (8)" +msgstr "octava (8)" + +#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199 +msgid "sixteenth (16)" +msgstr "d�ima sexta (16)" + +#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201 +msgid "thirty-second (32)" +msgstr "trig�ima segunda (32)" + +#: gtk_ardour/tempo_dialog.cc:301 +msgid "garbaged note type entry (%1)" +msgstr "se descart el texto (%1)" + +#: gtk_ardour/tempo_dialog.cc:311 +msgid "incomprehensible note type entry (%1)" +msgstr "El formato de este texto es incomprensible(%1)" + +#: gtk_ardour/time_axis_view.cc:95 +msgid "gTortnam" +msgstr "gTortnam" + +#: gtk_ardour/time_axis_view.cc:446 +msgid "Largest" +msgstr "Enorme" + +#: gtk_ardour/time_axis_view.cc:447 +msgid "Large" +msgstr "Grande" + +#: gtk_ardour/time_axis_view.cc:448 +msgid "Larger" +msgstr "Mayor" + +#: gtk_ardour/time_axis_view.cc:450 +msgid "Smaller" +msgstr "Menor" + +#: gtk_ardour/time_axis_view.cc:451 +msgid "Small" +msgstr "Chico" + +#: gtk_ardour/time_axis_view.cc:785 +msgid "unknown track height name \"%1\" in XML GUI information" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:69 +msgid "TimeAxisViewItemName" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:258 +msgid "new duration %1 frames is out of bounds for %2" +msgstr "" + +#: gtk_ardour/time_selection.cc:40 +msgid "programming error: request for non-existent audio range (%1)!" +msgstr "" + +#: gtk_ardour/utils.cc:57 +msgid "" +"\"\n" +"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+=" +msgstr "" + +#: gtk_ardour/utils.cc:66 +msgid "aeiou" +msgstr "" + +#: gtk_ardour/utils.cc:75 +msgid "AEIOU" +msgstr "" + +#: gtk_ardour/utils.cc:84 +msgid "bcdfghjklmnpqrtvwxyz" +msgstr "" + +#: gtk_ardour/utils.cc:93 +msgid "BCDFGHJKLMNPQRTVWXYZ" +msgstr "" + +#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265 +msgid "bad XPM header %1" +msgstr "" + +#: gtk_ardour/utils.cc:516 +msgid "missing RGBA style for \"%1\"" +msgstr "" + +#: gtk_ardour/visual_time_axis.cc:297 +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Realmente desea quitar la pista \"%1\" ?\n" +"(no podr�deshacer esto)" + +#: gtk_ardour/visual_time_axis.cc:385 +msgid "A track already exists with that name" +msgstr "Ya existe una pista con este nombre" + +#~ msgid "Export to CD" +#~ msgstr "Exportar a CD" + +#, fuzzy +#~ msgid "Trace MIDI Input" +#~ msgstr "Vigilar Entrada de MIDI" + +#, fuzzy +#~ msgid "Trace MIDI Output" +#~ msgstr "Vigilar Salida de MIDI" + +#~ msgid "MTC Port" +#~ msgstr "Puerto MTC" + +#~ msgid "attempt to timestretch a non-audio track!" +#~ msgstr "se intent hacer estiramiento a una pista que no es de audio!" + +#~ msgid "ardour: tempo editor" +#~ msgstr "ardour: editor de tempo" + +#~ msgid "ok" +#~ msgstr "ok" + +#, fuzzy +#~ msgid "apply" +#~ msgstr "aplicar" + +#, fuzzy +#~ msgid "Edit left" +#~ msgstr "Modo de edicin" + +#, fuzzy +#~ msgid "Edit right" +#~ msgstr "Editar con" + +#, fuzzy +#~ msgid "Edit fade" +#~ msgstr "Modo de edicin" + +#, fuzzy +#~ msgid "Export region" +#~ msgstr "Exportar regin" + +#, fuzzy +#~ msgid "Bounce region" +#~ msgstr "Grabar seleccin" + +#~ msgid "Region" +#~ msgstr "Regin" + +#~ msgid "Play selected region" +#~ msgstr "Reproducir regin selecionada" + +#~ msgid "clear connections" +#~ msgstr "Quitar conecciones" + +#, fuzzy +#~ msgid "outside this computer" +#~ msgstr "Ocultar esta pista" + +#, fuzzy +#~ msgid "inside this computer" +#~ msgstr "Ocultar esta pista" diff --git a/gtk2_ardour/po/fr_FR.po b/gtk2_ardour/po/fr_FR.po new file mode 100644 index 0000000000..479382a52a --- /dev/null +++ b/gtk2_ardour/po/fr_FR.po @@ -0,0 +1,5198 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2004 Paul Davis +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: gtk-ardour 0.334.5\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2005-09-19 18:09-0400\n" +"PO-Revision-Date: 2005-02-14 11:19-0500\n" +"Last-Translator: Alain Fréhel \n" +"Language-Team: French \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: gtk_ardour/about.cc:134 +msgid "Marcus Andersson" +msgstr "" + +#: gtk_ardour/about.cc:135 +msgid "Jeremy Hall" +msgstr "" + +#: gtk_ardour/about.cc:136 +msgid "Steve Harris" +msgstr "" + +#: gtk_ardour/about.cc:137 +msgid "Tim Mayberry" +msgstr "" + +#: gtk_ardour/about.cc:138 +msgid "Mark Stewart" +msgstr "" + +#: gtk_ardour/about.cc:139 +msgid "Sam Chessman" +msgstr "" + +#: gtk_ardour/about.cc:140 +msgid "Jack O'Quin" +msgstr "" + +#: gtk_ardour/about.cc:141 +msgid "Matt Krai" +msgstr "" + +#: gtk_ardour/about.cc:142 +msgid "Ben Bell" +msgstr "" + +#: gtk_ardour/about.cc:143 +msgid "Gerard van Dongen" +msgstr "" + +#: gtk_ardour/about.cc:144 +msgid "Thomas Charbonnel" +msgstr "" + +#: gtk_ardour/about.cc:145 +msgid "Nick Mainsbridge" +msgstr "" + +#: gtk_ardour/about.cc:146 +msgid "Colin Law" +msgstr "" + +#: gtk_ardour/about.cc:147 +msgid "Sampo Savolainen" +msgstr "" + +#: gtk_ardour/about.cc:148 +msgid "Joshua Leach" +msgstr "" + +#: gtk_ardour/about.cc:149 +msgid "Rob Holland" +msgstr "" + +#: gtk_ardour/about.cc:150 +msgid "Per Sigmond" +msgstr "" + +#: gtk_ardour/about.cc:151 +msgid "Doug Mclain" +msgstr "" + +#: gtk_ardour/about.cc:156 +msgid "" +"French:\n" +"\tAlain Fréhel " +msgstr "" +"Français :\n" +"\tAlain Fréhel " + +#: gtk_ardour/about.cc:157 +msgid "" +"German:\n" +"\tKarsten Petersen " +msgstr "" +"Allemand :\n" +"\tKarsten Petersen " + +#: gtk_ardour/about.cc:158 +msgid "" +"Italian:\n" +"\tFilippo Pappalardo " +msgstr "" +"Italien :\n" +"\tFilippo Pappalardo " + +#: gtk_ardour/about.cc:159 +msgid "" +"Portuguese:\n" +"\tRui Nuno Capela " +msgstr "" +"Portugais :\n" +"\tRui Nuno Capela " + +#: gtk_ardour/about.cc:160 +msgid "" +"Brazilian Portuguese:\n" +"\tAlexander da Franca Fernandes \n" +"\tChris Ross " +msgstr "" +"Portugais du Brésil :\n" +"\tAlexander da Franca Fernandes \n" +"\tChris Ross " + +#: gtk_ardour/about.cc:162 +msgid "" +"Spanish:\n" +"\t Alex Krohn " +msgstr "" +"Espagnol :\n" +"\tAlex Krohn " + +#: gtk_ardour/about.cc:163 +msgid "" +"Russian:\n" +"\t Igor Blinov " +msgstr "" +"Russe :\n" +"\tIgor Blinov " + +#: gtk_ardour/about.cc:181 +#, fuzzy +msgid "" +"Copyright (C) 1999-2005 Paul Davis\n" +"Ardour comes with ABSOLUTELY NO WARRANTY\n" +"This is free software, and you are welcome to redistribute it\n" +"under certain conditions; see the file COPYING for details.\n" +msgstr "" +"Copyright (C) 1999-2004 Paul Davis\n" +"Copyright (C) 1999-2005 Paul Davis\n" +"Ardour est distribué SANS AUCUNE GARANTIE\n" +"Ceci est un logiciel libre, et vous êtes encouragés à le distribuer\n" +"sous certaines conditions ; voir le fichier COPYING pour les détails.\n" + +#: gtk_ardour/about.cc:188 +#, fuzzy +msgid "" +"Ardour: %1\n" +"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)" +msgstr "" +"Ardour: %1\n" +"(fonctionnant avec ardour/gtk %2 libardour: %3.%4.%5)" + +#: gtk_ardour/about.cc:206 +msgid "" +"Primary author:\n" +"\tPaul Davis\n" +"\n" +"Major developers:\n" +"\tJesse Chappell\n" +"\tTaybin Rutkin\n" +"Contributors:\n" +"\t" +msgstr "" +"Auteur principal :\n" +"\tPaul Davis\n" +"\n" +"Développeurs principaux :\n" +"\tJesse Chappell\n" +"\tTaybin Rutkin\n" +"Contributeurs :\n" +"\t" + +#: gtk_ardour/about.cc:243 +msgid "Authors" +msgstr "Auteurs" + +#: gtk_ardour/about.cc:244 +msgid "Translators" +msgstr "Traducteurs" + +#: gtk_ardour/about.cc:361 +msgid "cannot open splash image file \"%1\"" +msgstr "impossible d'ouvrir l'image de l'écran de démarrage \"%1\"" + +#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33 +#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81 +#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977 +#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85 +#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777 +#: gtk_ardour/redirect_box.cc:900 +msgid "OK" +msgstr "OK" + +#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92 +#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046 +#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72 +#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982 +#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733 +#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000 +#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129 +#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785 +#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86 +#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072 +#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33 +#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161 +msgid "Cancel" +msgstr "Annuler" + +#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94 +msgid "Tracks" +msgstr "Pistes" + +#: gtk_ardour/add_route_dialog.cc:43 +msgid "Busses" +msgstr "Bus" + +#: gtk_ardour/add_route_dialog.cc:48 +msgid "ardour: add track/bus" +msgstr "ardour : ajouter piste/bus" + +#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81 +msgid "Add" +msgstr "Ajouter" + +#: gtk_ardour/add_route_dialog.cc:86 +msgid "Name (template)" +msgstr "Nom (modèle)" + +#: gtk_ardour/ardour_ui.cc:798 +msgid "" +"pre\n" +"roll" +msgstr "" +"pré\n" +"roll" + +#: gtk_ardour/ardour_ui.cc:799 +msgid "" +"post\n" +"roll" +msgstr "" +"post\n" +"roll" + +#: gtk_ardour/ardour_ui.cc:807 +msgid "% " +msgstr "% " + +#: gtk_ardour/ardour_ui.cc:808 +#, fuzzy +msgid "spring" +msgstr "spring" + +#: gtk_ardour/ardour_ui.cc:810 +#, fuzzy +msgid "" +"punch\n" +"in" +msgstr "" +"punch\n" +"in" + +#: gtk_ardour/ardour_ui.cc:811 +msgid "" +"punch\n" +"out" +msgstr "" +"punch\n" +"out" + +#: gtk_ardour/ardour_ui.cc:812 +msgid "" +"auto\n" +"return" +msgstr "" +"retour\n" +"auto" + +#: gtk_ardour/ardour_ui.cc:813 +msgid "" +"auto\n" +"play" +msgstr "" +"lecture\n" +"auto." + +#: gtk_ardour/ardour_ui.cc:814 +msgid "" +"auto\n" +"input" +msgstr "" +"entrée\n" +"auto." + +#: gtk_ardour/ardour_ui.cc:815 +msgid "click" +msgstr "clic" + +#: gtk_ardour/ardour_ui.cc:816 +msgid "" +"follow\n" +"PH" +msgstr "" +"suivre\n" +"TL" + +#: gtk_ardour/ardour_ui.cc:817 +msgid "AUDITIONING" +msgstr "ECOUTE" + +#: gtk_ardour/ardour_ui.cc:818 +msgid "SOLO" +msgstr "SOLO" + +#: gtk_ardour/ardour_ui.cc:870 +msgid "Percentage" +msgstr "Pourcentage" + +#: gtk_ardour/ardour_ui.cc:872 +msgid "Semitones" +msgstr "Demi-tons" + +#: gtk_ardour/ardour_ui.cc:875 +msgid "Sprung" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:877 +msgid "Wheel" +msgstr "Roulette" + +#: gtk_ardour/ardour_ui.cc:902 +msgid "" +"You cannot record-enable\n" +"track %1\n" +"because it has no input connections.\n" +"You would be wasting space recording silence." +msgstr "" +"Vous ne pouvez activer\n" +"l'enregistrement de la piste %1\n" +"car elle n'a pas de connections en entrée.\n" +"Vous gacheriez de l'espace en enregistrant du silence." + +#: gtk_ardour/ardour_ui.cc:1073 +msgid "quit" +msgstr "quitter" + +#: gtk_ardour/ardour_ui.cc:1082 +msgid "" +"Ardour was unable to save your session.\n" +"\n" +"If you still wish to quit, please use the\n" +"\n" +"\"Just quit\" option." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1107 +msgid "Save and %1" +msgstr "Enregistrer et %1" + +#: gtk_ardour/ardour_ui.cc:1112 +msgid "Just %1" +msgstr "Juste %1" + +#: gtk_ardour/ardour_ui.cc:1117 +msgid "Don't %1" +msgstr "Ne pas %1" + +#: gtk_ardour/ardour_ui.cc:1126 +msgid "session" +msgstr "session" + +#: gtk_ardour/ardour_ui.cc:1128 +msgid "snapshot" +msgstr "Instantané" + +#: gtk_ardour/ardour_ui.cc:1130 +msgid "" +"The %1\n" +"\"%2\"\n" +"has not been saved.\n" +"\n" +"Any changes made this time\n" +"will be lost unless you save it.\n" +"\n" +"What do you want to do?" +msgstr "" +"La session \"%1\"\n" +"n'a pas été enregistrée.\n" +"\n" +"Les changements effectués cette fois-ci\n" +"seront perdus à moins que vous ne les enregistriez.\n" +"\n" +"Que voulez-vous faire ?" + +#: gtk_ardour/ardour_ui.cc:1151 +msgid "Prompter" +msgstr "Prompter" + +#: gtk_ardour/ardour_ui.cc:1152 +msgid "ardour: save session?" +msgstr "ardour : enregistrer la session ?" + +#: gtk_ardour/ardour_ui.cc:1219 +#, c-format +msgid "disconnected" +msgstr "déconnecté" + +#: gtk_ardour/ardour_ui.cc:1226 +#, c-format +msgid "SR: %.1f kHz / %4.1f msecs" +msgstr "F.E. : %.1f kHz / %4.1f ms" + +#: gtk_ardour/ardour_ui.cc:1230 +#, c-format +msgid "SR: %u kHz / %4.1f msecs" +msgstr "F.E. : %u kHz / %4.1f ms" + +#: gtk_ardour/ardour_ui.cc:1243 +#, c-format +msgid "DSP Load: %.1f%%" +msgstr "Charge DSP : %.1f%%" + +#: gtk_ardour/ardour_ui.cc:1253 +#, c-format +msgid "Disk r:%5.1f w:%5.1f MB/s" +msgstr "Disque l:%5.1f e:%5.1f Mo/s" + +#: gtk_ardour/ardour_ui.cc:1267 +#, c-format +msgid "Buffers p:%%% c:%%%" +msgstr "Tampons p:%%% c:%%%" + +#: gtk_ardour/ardour_ui.cc:1294 +msgid "space: 24hrs+" +msgstr "espace : 24hrs+" + +#: gtk_ardour/ardour_ui.cc:1324 +#, c-format +msgid "space: %02dh:%02dm:%02ds" +msgstr "espace: %02dh:%02dm:%02ds" + +#: gtk_ardour/ardour_ui.cc:1575 +msgid "programming error: impossible control method" +msgstr "erreur de programmation : méthode de contrôle impossible" + +#: gtk_ardour/ardour_ui.cc:1800 +msgid "cancel" +msgstr "annuler" + +#: gtk_ardour/ardour_ui.cc:1801 +msgid "rescan" +msgstr "rafraîchir" + +#: gtk_ardour/ardour_ui.cc:1842 +msgid "open session" +msgstr "ouvrir session" + +#: gtk_ardour/ardour_ui.cc:1897 +msgid "Patience is a virtue.\n" +msgstr "La patience est une vertue.\n" + +#: gtk_ardour/ardour_ui.cc:1906 +msgid "You cannot add a track without a session already loaded." +msgstr "" +"Vous ne pouvez pas ajouter une piste sans qu'une session ait été chargée." + +#: gtk_ardour/ardour_ui.cc:1913 +msgid "could not create new audio track" +msgstr "impossible de créer une nouvelle piste audio" + +#: gtk_ardour/ardour_ui.cc:1917 +msgid "could not create new audio bus" +msgstr "impossible de créer un nouveau bus audio" + +#: gtk_ardour/ardour_ui.cc:1936 +msgid "" +"There are insufficient JACK ports available\n" +"to create a new track or bus.\n" +"You should save Ardour, exit and\n" +"restart JACK with more ports." +msgstr "" +"Il n'y a pas assez de ports JACK disponibles\n" +"pour créer une nouvelle piste ou bus.\n" +"Vous devriez enregistrer, quitter, puis\n" +"redémarrer JACK avec plus de ports." + +#: gtk_ardour/ardour_ui.cc:2071 +msgid "" +"Please create 1 or more track\n" +"before trying to record.\n" +"Check the Session menu." +msgstr "" +"Veuillez créer une ou plusieurs pistes supplémentaires\n" +"avant d'essayer d'enregistrer.\n" +"Regardez dans le menu Session." + +#: gtk_ardour/ardour_ui.cc:2312 +msgid "" +"JACK has either been shutdown or it\n" +"disconnected Ardour because Ardour\n" +"was not fast enough. You can save the\n" +"session and/or try to reconnect to JACK ." +msgstr "" +"Soit JACK a été arrêté, soit il a déconnecté\n" +"Ardour parce que celui-ci n'était pas assez rapide.\n" +"Vous devriez enregistrer la session\n" +"et/ou essayer de le reconnecter à JACK." + +#: gtk_ardour/ardour_ui.cc:2328 +msgid "Unable to create all required ports" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2336 +msgid "Unable to start the session running" +msgstr "Impossible de lancer la session" + +#: gtk_ardour/ardour_ui.cc:2472 +msgid "No Stream" +msgstr "Pas de flux" + +#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518 +msgid "none" +msgstr "aucun" + +#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527 +#: gtk_ardour/automation_time_axis.cc:189 +#: gtk_ardour/automation_time_axis.cc:218 +#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211 +#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947 +#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659 +msgid "off" +msgstr "arrêt" + +#: gtk_ardour/ardour_ui.cc:2548 +msgid "Name for snapshot" +msgstr "Nom de l'instantané" + +#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294 +msgid "Name for mix template:" +msgstr "Nom du modèle de mélange : " + +#: gtk_ardour/ardour_ui.cc:2717 +msgid "-template" +msgstr "-modèle" + +#: gtk_ardour/ardour_ui.cc:2760 +msgid "Session %1 already exists at %2" +msgstr "La session %1 existe déjà en %2" + +#: gtk_ardour/ardour_ui.cc:2832 +msgid "" +"You do not have write access to this session.\n" +"This prevents the session from being loaded." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897 +msgid "Session \"%1 (snapshot %2)\" did not load successfully" +msgstr "La session \"%1 (instantané %2)\" ne s'est pas chargée correctement" + +#: gtk_ardour/ardour_ui.cc:2966 +msgid "" +"No audio files were ready for cleanup\n" +"\n" +"If this seems suprising, check for any existing\n" +"snapshots. These may still include regions that\n" +"require some unused files to continue to exist." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001 +msgid "files" +msgstr "fichiers" + +#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003 +msgid "file" +msgstr "fichier" + +#: gtk_ardour/ardour_ui.cc:3026 +msgid "ardour: cleanup" +msgstr "ardour : nettoyage" + +#: gtk_ardour/ardour_ui.cc:3040 +msgid "" +"Cleanup is a destructive operation.\n" +"ALL undo/redo information will be lost if you cleanup.\n" +"Unused audio files will be moved to a \"dead sounds\" location." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3045 +msgid "Proceed with cleanup" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3061 +#, fuzzy +msgid "CleanupDialog" +msgstr "Nettoyer" + +#: gtk_ardour/ardour_ui.cc:3062 +#, fuzzy +msgid "ardour cleanup" +msgstr "ardour : nettoyage" + +#: gtk_ardour/ardour_ui.cc:3063 +#, fuzzy +msgid "ardour_cleanup" +msgstr "ardour : nettoyage" + +#: gtk_ardour/ardour_ui.cc:3086 +msgid "cleaned files" +msgstr "fichiers nettoyés" + +#: gtk_ardour/ardour_ui.cc:3087 +msgid "" +"The following %1 %2 were not in use.\n" +"The next time you flush the wastebasket\n" +"it will release an additional %3 %4bytes\n" +"of disk space" +msgstr "" +"Les %1 %2 fichiers suivants n'étaient pas utilisés.\n" +"La prochaine fois que vous viderez la corbeille,\n" +"%3 %4-octets d'espace disque supplémentaires seront\n" +"libérés" + +#: gtk_ardour/ardour_ui.cc:3110 +msgid "deleted file" +msgstr "fichiers effacés" + +#: gtk_ardour/ardour_ui.cc:3111 +#, fuzzy +msgid "" +"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space" +msgstr "" +"Les %1 fichier%2 suivant%2 seront effacé%2, libérant %3 %4-octets d'espace " +"disque" + +#: gtk_ardour/ardour_ui.cc:3226 +msgid "Recording was stopped because your system could not keep up." +msgstr "" +"L'enregistrement a été stoppé parce que votre système ne peut pas suivre." + +#: gtk_ardour/ardour_ui.cc:3248 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to write data to disk\n" +"quickly enough to keep up with recording.\n" +msgstr "" +"Le disque dur n'arrive pas\n" +"à suivre Ardour.\n" +"\n" +"Plus précisement, il a été incapable d'écrire les données\n" +"sur le disque assez rapidement pour suivre l'enregistrement.\n" + +#: gtk_ardour/ardour_ui.cc:3266 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to read data from disk\n" +"quickly enough to keep up with playback.\n" +msgstr "" +"Le disque dur n'arrive pas\n" +"à suivre Ardour.\n" +"\n" +"Plus précisement, il a été incapable de lire les données\n" +"sur le disque assez rapidement pour suivre la lecture.\n" + +#: gtk_ardour/ardour_ui.cc:3291 +msgid "Recover from crash" +msgstr "Récupérer après un plantage" + +#: gtk_ardour/ardour_ui.cc:3292 +msgid "Ignore crash data" +msgstr "Ignorer les données du plantage" + +#: gtk_ardour/ardour_ui.cc:3293 +msgid "" +"This session appears to have been in\n" +"middle of recording when ardour or\n" +"the computer was shutdown.\n" +"\n" +"Ardour can recover any captured audio for\n" +"you, or it can ignore it. Please decide\n" +"what you would like to do.\n" +msgstr "" +"Cette session semble avoir été interrompue\n" +"au milieu d'un enregistrement lorsque ardour ou\n" +"l'ordinateur s'est arrêté.\n" +"\n" +"Ardour peut récupérer pour vous tout ce qui a été enregistré,\n" +"ou vous pouvez l'ignorer. Veuillez décider\n" +"sur ce que vous voulez faire.\n" + +#: gtk_ardour/ardour_ui.cc:3338 +msgid "Could not disconnect from JACK" +msgstr "Impossible de se déconnecter de JACK" + +#: gtk_ardour/ardour_ui.cc:3351 +msgid "Could not reconnect to JACK" +msgstr "Impossible de se reconnecter à JACK" + +#: gtk_ardour/ardour_ui2.cc:60 +msgid "UI: cannot setup editor" +msgstr "IHM : impossible d'initialiser l'éditeur" + +#: gtk_ardour/ardour_ui2.cc:65 +msgid "UI: cannot setup mixer" +msgstr "IHM : impossible d'initialiser la console de mixage" + +#: gtk_ardour/ardour_ui2.cc:70 +#, fuzzy +msgid "UI: cannot setup meter_bridge" +msgstr "IHM : impossible d'initialiser le bandeau_vu-mètre" + +#: gtk_ardour/ardour_ui2.cc:98 +msgid "MMC + Local" +msgstr "MMC + Local" + +#: gtk_ardour/ardour_ui2.cc:99 +msgid "MMC" +msgstr "MMC" + +#: gtk_ardour/ardour_ui2.cc:100 +msgid "Local" +msgstr "Local" + +#: gtk_ardour/ardour_ui2.cc:117 +msgid "MMC ID" +msgstr "ID MMC" + +#: gtk_ardour/ardour_ui2.cc:215 +msgid "Play from playhead" +msgstr "Jouer depuis la tête de lecture" + +#: gtk_ardour/ardour_ui2.cc:216 +msgid "Stop playback" +msgstr "Arrêter la lecture" + +#: gtk_ardour/ardour_ui2.cc:217 +msgid "Play range/selection" +msgstr "Jouer l'intervalle/la sélection" + +#: gtk_ardour/ardour_ui2.cc:218 +msgid "Go to start of session" +msgstr "Aller au début de la session" + +#: gtk_ardour/ardour_ui2.cc:219 +msgid "Go to end of session" +msgstr "Aller à la fin de la session" + +#: gtk_ardour/ardour_ui2.cc:220 +msgid "Play loop range" +msgstr "Jouer l'intervalle de boucle" + +#: gtk_ardour/ardour_ui2.cc:221 +msgid "Return to last playback start when stopped" +msgstr "Revenir au dernier départ de lecture lors de l'arrêt" + +#: gtk_ardour/ardour_ui2.cc:222 +msgid "Start playback after any locate" +msgstr "Démarrer la lecture aprés chaque locate" + +#: gtk_ardour/ardour_ui2.cc:223 +msgid "Be sensible about input monitoring" +msgstr "Être raisonnable avec la pré-écoute des entrées" + +#: gtk_ardour/ardour_ui2.cc:224 +msgid "Start recording at auto-punch start" +msgstr "Démarrer l'enregistrement en début d'auto-punch" + +#: gtk_ardour/ardour_ui2.cc:225 +msgid "Stop recording at auto-punch end" +msgstr "Arrêter l'enregistrement en fin d'auto-punch" + +#: gtk_ardour/ardour_ui2.cc:226 +msgid "Enable/Disable audio click" +msgstr "Activer/Désactiver le clic sonore" + +#: gtk_ardour/ardour_ui2.cc:227 +msgid "Enable/Disable follow playhead" +msgstr "Activer/Désactiver la poursuite de la tête de lecture" + +#: gtk_ardour/ardour_ui2.cc:228 +#, fuzzy +msgid "Shuttle speed control" +msgstr "Contrôle de la vitesse avec molette" + +#: gtk_ardour/ardour_ui2.cc:229 +#, fuzzy, c-format +msgid "Select semitones or %%-age for speed display" +msgstr "Sélectionner les demi-tons ou le %-age pour l'affichage de la vitesse" + +#: gtk_ardour/ardour_ui2.cc:230 +#, fuzzy +msgid "Select sprung or wheel behaviour" +msgstr "Sélectionner le comportement du ressort ou de la roulette" + +#: gtk_ardour/ardour_ui2.cc:231 +msgid "Current transport speed" +msgstr "Vitesse de transport courante" + +#: gtk_ardour/ardour_ui2.cc:312 +msgid "Primary clock" +msgstr "Horloge principale" + +#: gtk_ardour/ardour_ui2.cc:313 +msgid "secondary clock" +msgstr "Horloge secondaire" + +#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751 +#: gtk_ardour/ardour_ui2.cc:770 +msgid "stopped" +msgstr "arrêté" + +#: gtk_ardour/ardour_ui2.cc:431 +msgid "ardour: clock" +msgstr "ardour : horloge" + +#: gtk_ardour/ardour_ui2.cc:721 +msgid "st" +msgstr "er" + +#: gtk_ardour/ardour_ui2.cc:731 +msgid "sprung" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:742 +msgid "wheel" +msgstr "roulette" + +#: gtk_ardour/ardour_ui_dependents.cc:74 +#, fuzzy +msgid "keyboard_target: error setting binding state: invalid node" +msgstr "keyboard_target: error setting binding state: noeud invalide" + +#: gtk_ardour/ardour_ui_dialogs.cc:158 +msgid "close session" +msgstr "fermer la session" + +#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895 +msgid "New" +msgstr "Nouveau" + +#: gtk_ardour/ardour_ui_ed.cc:76 +msgid "Open" +msgstr "Ouvrir" + +#: gtk_ardour/ardour_ui_ed.cc:77 +msgid "Recent" +msgstr "Récent" + +#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +msgid "Close" +msgstr "Fermer" + +#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488 +msgid "Add Track/Bus" +msgstr "Ajouter piste/bus" + +#: gtk_ardour/ardour_ui_ed.cc:99 +msgid "Connect" +msgstr "Connecter" + +#: gtk_ardour/ardour_ui_ed.cc:100 +msgid "Image Compositor" +msgstr "Compositeur d'image" + +#: gtk_ardour/ardour_ui_ed.cc:114 +msgid "Save" +msgstr "Enregistrer" + +#: gtk_ardour/ardour_ui_ed.cc:118 +msgid "Snapshot" +msgstr "Instantané" + +#: gtk_ardour/ardour_ui_ed.cc:126 +msgid "Save Template..." +msgstr "Enregistrer le modèle..." + +#: gtk_ardour/ardour_ui_ed.cc:133 +msgid "Export session to audiofile..." +msgstr "Exporter la session dans un fichier audio..." + +#: gtk_ardour/ardour_ui_ed.cc:134 +#, fuzzy +msgid "Export range to audiofile..." +msgstr "Exporter la range dans un fichier audio..." + +#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312 +#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118 +#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227 +msgid "Export" +msgstr "Exporter" + +#: gtk_ardour/ardour_ui_ed.cc:146 +msgid "Cleanup unused sources" +msgstr "Nettoyer les sources inutilisées" + +#: gtk_ardour/ardour_ui_ed.cc:147 +msgid "Flush wastebasket" +msgstr "Vider la corbeille" + +#: gtk_ardour/ardour_ui_ed.cc:149 +msgid "Cleanup" +msgstr "Nettoyer" + +#: gtk_ardour/ardour_ui_ed.cc:154 +msgid "Quit" +msgstr "Quitter" + +#: gtk_ardour/ardour_ui_ed.cc:156 +msgid "Session" +msgstr "Session" + +#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287 +#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499 +#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570 +#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412 +msgid "Edit" +msgstr "Édition" + +#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572 +#: gtk_ardour/mixer_strip.cc:631 +msgid "Disconnect" +msgstr "Déconnecter" + +#: gtk_ardour/ardour_ui_ed.cc:174 +msgid "Reconnect" +msgstr "Reconnecter" + +#: gtk_ardour/ardour_ui_ed.cc:192 +msgid "Latency" +msgstr "Latence" + +#: gtk_ardour/ardour_ui_ed.cc:195 +msgid "JACK" +msgstr "JACK" + +#: gtk_ardour/ardour_ui_ed.cc:205 +msgid "Editor" +msgstr "Éditeur" + +#: gtk_ardour/ardour_ui_ed.cc:206 +msgid "Mixer" +msgstr "Console de mixage" + +#: gtk_ardour/ardour_ui_ed.cc:212 +msgid "Options Editor" +msgstr "Éditeur d'options" + +#: gtk_ardour/ardour_ui_ed.cc:219 +msgid "Audio Library" +msgstr "Bibliothèque audio" + +#: gtk_ardour/ardour_ui_ed.cc:225 +msgid "Track/Bus Inspector" +msgstr "Inspecteur de pistes/bus" + +#: gtk_ardour/ardour_ui_ed.cc:232 +msgid "Connections" +msgstr "Connexions" + +#: gtk_ardour/ardour_ui_ed.cc:240 +msgid "Meter Bridge" +msgstr "Bandeau de vu-mètre" + +#: gtk_ardour/ardour_ui_ed.cc:248 +msgid "Locations" +msgstr "Emplacements" + +#: gtk_ardour/ardour_ui_ed.cc:255 +msgid "Big Clock" +msgstr "Grande horloge" + +#: gtk_ardour/ardour_ui_ed.cc:261 +msgid "About" +msgstr "À propos" + +#: gtk_ardour/ardour_ui_ed.cc:264 +msgid "Windows" +msgstr "Fenêtres" + +#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203 +msgid "SMPTE" +msgstr "SMPTE" + +#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202 +#: gtk_ardour/editor_rulers.cc:359 +msgid "Bars:Beats" +msgstr "Mesures:Temps" + +#: gtk_ardour/audio_clock.cc:1642 +msgid "Minutes:Seconds" +msgstr "Minutes:Secondes" + +#: gtk_ardour/audio_clock.cc:1643 +msgid "Audio Frames" +msgstr "Trames audio" + +#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356 +#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713 +#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774 +#: gtk_ardour/option_editor.cc:794 +msgid "Off" +msgstr "Arrêt" + +#: gtk_ardour/audio_clock.cc:1646 +msgid "Mode" +msgstr "Mode" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523 +msgid "m" +msgstr "m" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524 +msgid "s" +msgstr "s" + +#: gtk_ardour/audio_time_axis.cc:104 +msgid "r" +msgstr "r" + +#: gtk_ardour/audio_time_axis.cc:108 +msgid "g" +msgstr "g" + +#: gtk_ardour/audio_time_axis.cc:109 +msgid "p" +msgstr "p" + +#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44 +#: gtk_ardour/visual_time_axis.cc:90 +msgid "h" +msgstr "h" + +#: gtk_ardour/audio_time_axis.cc:111 +msgid "a" +msgstr "a" + +#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89 +msgid "v" +msgstr "v" + +#: gtk_ardour/audio_time_axis.cc:185 +msgid "Record" +msgstr "Enregistrer" + +#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191 +msgid "Solo" +msgstr "Solo" + +#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236 +#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433 +msgid "Mute" +msgstr "Muet" + +#: gtk_ardour/audio_time_axis.cc:188 +msgid "Edit Group" +msgstr "Groupe d'édition" + +#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110 +msgid "Display Height" +msgstr "Hauteur de l'affichage" + +#: gtk_ardour/audio_time_axis.cc:190 +msgid "Playlist" +msgstr "Liste de lecture" + +#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752 +msgid "Automation" +msgstr "Automatisation" + +#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111 +msgid "Visual options" +msgstr "Options d'affichage" + +#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112 +msgid "Hide this track" +msgstr "Cacher cette piste" + +#: gtk_ardour/audio_time_axis.cc:349 +msgid "No group" +msgstr "Pas de groupe" + +#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447 +#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229 +msgid "Height" +msgstr "Hauteur" + +#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266 +#: gtk_ardour/marker_time_axis.cc:230 +msgid "Color" +msgstr "Couleur" + +#: gtk_ardour/audio_time_axis.cc:720 +#, fuzzy +msgid "Hide all crossfades" +msgstr "Cacher tous les fondus enchaînés" + +#: gtk_ardour/audio_time_axis.cc:721 +#, fuzzy +msgid "Show all crossfades" +msgstr "Montrer tous les fondus enchaînés" + +#: gtk_ardour/audio_time_axis.cc:729 +msgid "show all automation" +msgstr "montrer toute l'automatisation" + +#: gtk_ardour/audio_time_axis.cc:732 +msgid "show existing automation" +msgstr "montrer l'automatisation existante" + +#: gtk_ardour/audio_time_axis.cc:735 +msgid "hide all automation" +msgstr "cacher toute l'automatisation" + +#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204 +#: gtk_ardour/editor.cc:234 +msgid "gain" +msgstr "gain" + +#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244 +msgid "pan" +msgstr "panoramique" + +#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388 +msgid "Plugins" +msgstr "Greffons" + +#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95 +msgid "Show waveforms" +msgstr "Montrer les formes d'onde" + +#: gtk_ardour/audio_time_axis.cc:766 +msgid "Traditional" +msgstr "Traditionnel" + +#: gtk_ardour/audio_time_axis.cc:769 +msgid "Rectified" +msgstr "Rectifié" + +#: gtk_ardour/audio_time_axis.cc:772 +msgid "Waveform" +msgstr "Forme d'onde" + +#: gtk_ardour/audio_time_axis.cc:782 +msgid "align with existing material" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:787 +msgid "align with capture time" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:793 +#, fuzzy +msgid "Alignment" +msgstr "Aligner" + +#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288 +msgid "Active" +msgstr "Actif" + +#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386 +#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467 +#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269 +#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233 +#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83 +msgid "Remove" +msgstr "Enlever" + +#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880 +#: gtk_ardour/audio_time_axis.cc:911 +msgid "Name for playlist" +msgstr "Nom de la liste de lecture" + +#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433 +msgid "a track already exists with that name" +msgstr "une piste avec le même nom existe déjà" + +#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001 +#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539 +msgid "programming error: " +msgstr "erreur de programmation : " + +#: gtk_ardour/audio_time_axis.cc:1889 +msgid "Current: %1" +msgstr "Courant : %1" + +#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452 +#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226 +#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377 +msgid "Rename" +msgstr "Renommer" + +#: gtk_ardour/audio_time_axis.cc:1896 +msgid "New Copy" +msgstr "Nouvelle copie" + +#: gtk_ardour/audio_time_axis.cc:1898 +#, fuzzy +msgid "Clear Current" +msgstr "Effacer courante" + +#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472 +#: gtk_ardour/editor.cc:2557 +msgid "Select" +msgstr "Sélectionner" + +#: gtk_ardour/automation_line.cc:904 +#, fuzzy +msgid "automation event move" +msgstr "déplacement d'évenement d'automatisation" + +#: gtk_ardour/automation_line.cc:906 +#, fuzzy +msgid "automation range drag" +msgstr "déplacement d'intervalle d'automatisation" + +#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64 +#, fuzzy +msgid "remove control point" +msgstr "Enlever le point de contrôle" + +#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010 +msgid "clear" +msgstr "effacer" + +#: gtk_ardour/automation_time_axis.cc:80 +msgid "track height" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:81 +#, fuzzy +msgid "automation state" +msgstr "état de l'automatisation de panoramique" + +#: gtk_ardour/automation_time_axis.cc:82 +#, fuzzy +msgid "clear track" +msgstr "effacer les intervalles" + +#: gtk_ardour/automation_time_axis.cc:83 +#, fuzzy +msgid "hide track" +msgstr "décaler la piste" + +#: gtk_ardour/automation_time_axis.cc:191 +#: gtk_ardour/automation_time_axis.cc:229 +#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213 +#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419 +#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50 +msgid "play" +msgstr "jouer" + +#: gtk_ardour/automation_time_axis.cc:193 +#: gtk_ardour/automation_time_axis.cc:240 +#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215 +#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422 +#: gtk_ardour/plugin_ui.cc:663 +msgid "write" +msgstr "écrire" + +#: gtk_ardour/automation_time_axis.cc:195 +#: gtk_ardour/automation_time_axis.cc:251 +#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217 +#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953 +#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665 +#, fuzzy +msgid "touch" +msgstr "toucher" + +#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274 +#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428 +msgid "???" +msgstr "???" + +#: gtk_ardour/automation_time_axis.cc:276 +#, fuzzy +msgid "clear automation" +msgstr "effacer l'automatisation" + +#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453 +#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398 +msgid "Hide" +msgstr "Cacher" + +#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52 +#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364 +msgid "Clear" +msgstr "Effacer" + +#: gtk_ardour/automation_time_axis.cc:474 +msgid "State" +msgstr "État" + +#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49 +msgid "Input Connections" +msgstr "Connexions en entrée" + +#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48 +msgid "Output Connections" +msgstr "Connexions en sortie" + +#: gtk_ardour/connection_editor.cc:49 +msgid "New Input" +msgstr "Nouvelle entrée" + +#: gtk_ardour/connection_editor.cc:50 +msgid "New Output" +msgstr "Nouvelle sortie" + +#: gtk_ardour/connection_editor.cc:51 +msgid "Delete" +msgstr "Supprimer" + +#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96 +msgid "Add Port" +msgstr "Ajouter un port" + +#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105 +#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786 +msgid "Rescan" +msgstr "Rafraîchir" + +#: gtk_ardour/connection_editor.cc:101 +msgid "Available Ports" +msgstr "Ports disponibles" + +#: gtk_ardour/connection_editor.cc:183 +msgid "ardour: connections" +msgstr "ardour : connexions" + +#: gtk_ardour/connection_editor.cc:513 +#, c-format +msgid "in %d" +msgstr "en %d" + +#: gtk_ardour/connection_editor.cc:644 +msgid "Name for new connection:" +msgstr "Nom de la nouvelle connexion :" + +#: gtk_ardour/crossfade_edit.cc:71 +msgid "crossfade editor" +msgstr "éditeur de fondu enchaîné" + +#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449 +msgid "Reset" +msgstr "Réinitialiser" + +#: gtk_ardour/crossfade_edit.cc:78 +msgid "Fade" +msgstr "Fondu" + +#: gtk_ardour/crossfade_edit.cc:79 +#, fuzzy +msgid "Out (dry)" +msgstr "Sortie (sec)" + +#: gtk_ardour/crossfade_edit.cc:80 +#, fuzzy +msgid "Out" +msgstr "Sortie" + +#: gtk_ardour/crossfade_edit.cc:81 +#, fuzzy +msgid "In (dry)" +msgstr "Entrée (sec)" + +#: gtk_ardour/crossfade_edit.cc:82 +msgid "In" +msgstr "Entrée" + +#: gtk_ardour/crossfade_edit.cc:84 +#, fuzzy +msgid "With Pre-roll" +msgstr "Avec pré-roll" + +#: gtk_ardour/crossfade_edit.cc:85 +#, fuzzy +msgid "With Post-roll" +msgstr "Avec post-roll" + +#: gtk_ardour/crossfade_edit.cc:93 +msgid "Fade In" +msgstr "Fondu d'ouverture" + +#: gtk_ardour/crossfade_edit.cc:94 +msgid "Fade Out" +msgstr "Fondu de fermeture" + +#: gtk_ardour/crossfade_edit.cc:98 +msgid "ardour: x-fade edit" +msgstr "ardour : édition fondu enchaîné" + +#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311 +#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189 +msgid "Audition" +msgstr "Audition" + +#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804 +msgid "Regions/name" +msgstr "Régions/nom" + +#: gtk_ardour/editor.cc:108 +msgid "Chunks" +msgstr "Fragments" + +#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079 +msgid "Slide" +msgstr "Curseur" + +#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077 +msgid "Splice" +msgstr "Réunion" + +#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136 +#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96 +#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977 +msgid "None" +msgstr "Aucun" + +#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124 +#, fuzzy +msgid "CD Frames" +msgstr "Trames CD" + +#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126 +#, fuzzy +msgid "SMPTE Frames" +msgstr "Trames SMPTE" + +#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128 +msgid "SMPTE Seconds" +msgstr "Secondes SMPTE" + +#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130 +msgid "SMPTE Minutes" +msgstr "Minutes SMPTE" + +#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132 +msgid "Seconds" +msgstr "Secondes" + +#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134 +msgid "Minutes" +msgstr "Minutes" + +#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106 +msgid "Beats/32" +msgstr "Temps/32" + +#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104 +msgid "Beats/16" +msgstr "Temps/16" + +#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102 +msgid "Beats/8" +msgstr "Temps/8" + +#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100 +msgid "Beats/4" +msgstr "Temps/4" + +#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098 +msgid "Beats/3" +msgstr "Temps/3" + +#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108 +msgid "Beats" +msgstr "Temps" + +#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110 +msgid "Bars" +msgstr "Mesures" + +#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112 +msgid "Marks" +msgstr "Marques" + +#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114 +#: gtk_ardour/editor.cc:4182 +msgid "Edit Cursor" +msgstr "Curseur d'édition" + +#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116 +#, fuzzy +msgid "Region starts" +msgstr "Débuts de régions" + +#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118 +#, fuzzy +msgid "Region ends" +msgstr "Fins de régions" + +#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122 +#, fuzzy +msgid "Region syncs" +msgstr "Syncro. de régions" + +#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120 +#, fuzzy +msgid "Region bounds" +msgstr "Limites de régions" + +#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153 +#: gtk_ardour/time_axis_view.cc:449 +msgid "Normal" +msgstr "Normal" + +#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155 +msgid "Magnetic" +msgstr "Magnétique" + +#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174 +#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237 +msgid "Left" +msgstr "Gauche" + +#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176 +#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238 +msgid "Right" +msgstr "Droite" + +#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178 +msgid "Center" +msgstr "Centre" + +#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180 +msgid "Playhead" +msgstr "Tête de lecture" + +#: gtk_ardour/editor.cc:201 +msgid "Mins:Secs" +msgstr "Mins:Secs" + +#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353 +msgid "Frames" +msgstr "Trames" + +#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373 +msgid "Tempo" +msgstr "Tempo" + +#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367 +msgid "Meter" +msgstr "Vu-mètre" + +#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379 +msgid "Location Markers" +msgstr "Marqueurs d'emplacements" + +#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385 +msgid "Range Markers" +msgstr "Marqueurs d'intervalle" + +#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391 +msgid "Loop/Punch Ranges" +msgstr "Intervalles de boucle/punch" + +#: gtk_ardour/editor.cc:221 +msgid "" +"editor\n" +"mixer" +msgstr "" +"éditeur\n" +"console de mixage" + +#: gtk_ardour/editor.cc:232 +msgid "range" +msgstr "intervalle" + +#: gtk_ardour/editor.cc:233 +msgid "object" +msgstr "objet" + +#: gtk_ardour/editor.cc:235 +msgid "zoom" +msgstr "zoom" + +#: gtk_ardour/editor.cc:236 +#, fuzzy +msgid "timefx" +msgstr "Effet temporel" + +#: gtk_ardour/editor.cc:237 +msgid "listen" +msgstr "écouter" + +#: gtk_ardour/editor.cc:239 +msgid "mode" +msgstr "mode" + +#: gtk_ardour/editor.cc:240 +msgid "automation" +msgstr "automatisation" + +#: gtk_ardour/editor.cc:242 +msgid "Edit Mode" +msgstr "Mode d'édition" + +#: gtk_ardour/editor.cc:243 +#, fuzzy +msgid "Snap To" +msgstr "Snap to" + +#: gtk_ardour/editor.cc:244 +#, fuzzy +msgid "Snap Mode" +msgstr "Snap mode" + +#: gtk_ardour/editor.cc:245 +msgid "Zoom Focus" +msgstr "Focus du zoom" + +#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364 +#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579 +msgid "Nudge" +msgstr "Décaler" + +#: gtk_ardour/editor.cc:511 +msgid "Zoom in" +msgstr "Zoom avant" + +#: gtk_ardour/editor.cc:512 +msgid "Zoom out" +msgstr "Zoom arrière" + +#: gtk_ardour/editor.cc:517 +msgid "Zoom to session" +msgstr "Zoomer vers la session" + +#: gtk_ardour/editor.cc:536 +#, fuzzy +msgid "Zoom Span" +msgstr "Largeur du zoom" + +#: gtk_ardour/editor.cc:566 +msgid "Edit Groups" +msgstr "Groupes d'édition" + +#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142 +msgid "-all-" +msgstr "-tout-" + +#: gtk_ardour/editor.cc:718 +msgid "Nudge region/selection forwards" +msgstr "Décaller région/sélection vers l'avant" + +#: gtk_ardour/editor.cc:719 +msgid "Nudge region/selection backwards" +msgstr "Décaller région/sélection vers l'arrière" + +#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308 +msgid "ardour: editor" +msgstr "ardour : éditeur" + +#: gtk_ardour/editor.cc:729 +msgid "ardour_editor" +msgstr "ardour_éditeur" + +#: gtk_ardour/editor.cc:846 +msgid "VerboseCanvasCursor" +msgstr "VerboseCanvasCursor" + +#: gtk_ardour/editor.cc:1405 +msgid "FirstActionMessage" +msgstr "FirstActionCursor" + +#: gtk_ardour/editor.cc:1407 +msgid "Start a new session\n" +msgstr "Commencer une nouvelle session\n" + +#: gtk_ardour/editor.cc:1408 +msgid "via Session menu" +msgstr "via le menu Session" + +#: gtk_ardour/editor.cc:1703 +msgid "ardour: editor: " +msgstr "ardour : éditeur : " + +#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796 +#: gtk_ardour/editor_markers.cc:797 +msgid "Loop" +msgstr "Boucle" + +#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810 +#: gtk_ardour/editor_markers.cc:823 +msgid "Punch" +msgstr "Insérer" + +#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688 +msgid "programming error: fade in canvas item has no regionview data pointer!" +msgstr "programming error: fade in canvas item has no regionview data pointer!" + +#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986 +#: gtk_ardour/redirect_box.cc:401 +msgid "Deactivate" +msgstr "Désactiver" + +#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988 +#: gtk_ardour/redirect_box.cc:398 +msgid "Activate" +msgstr "Activer" + +#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993 +msgid "Linear" +msgstr "Linéaire" + +#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994 +#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734 +#: gtk_ardour/option_editor.cc:796 +msgid "Slowest" +msgstr "Plus lent" + +#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995 +#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735 +#: gtk_ardour/option_editor.cc:798 +msgid "Slow" +msgstr "Lent" + +#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996 +#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737 +#: gtk_ardour/option_editor.cc:802 +msgid "Fast" +msgstr "Rapide" + +#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997 +#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739 +#: gtk_ardour/option_editor.cc:806 +msgid "Fastest" +msgstr "Plus rapide" + +#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113 +msgid "Freeze" +msgstr "Bloquer" + +#: gtk_ardour/editor.cc:2109 +msgid "Unfreeze" +msgstr "Débloquer" + +#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328 +#, fuzzy +msgid "Unmute" +msgstr "Non muet" + +#: gtk_ardour/editor.cc:2247 +msgid "Convert to short" +msgstr "Convertir en court" + +#: gtk_ardour/editor.cc:2249 +msgid "Convert to full" +msgstr "Convertir en complet" + +#: gtk_ardour/editor.cc:2260 +#, fuzzy +msgid "Crossfade" +msgstr "Modèle de fondu enchaîné" + +#: gtk_ardour/editor.cc:2303 +msgid "Popup region editor" +msgstr "Ouvrir l'éditeur de région" + +#: gtk_ardour/editor.cc:2304 +msgid "Raise to top layer" +msgstr "Monter vers la couche du haut" + +#: gtk_ardour/editor.cc:2305 +msgid "Lower to bottom layer" +msgstr "Descendre vers la couche du bas" + +#: gtk_ardour/editor.cc:2307 +msgid "Define sync point" +msgstr "Définir le point de synchronisation" + +#: gtk_ardour/editor.cc:2308 +msgid "Remove sync point" +msgstr "Enlever le point de synchronisation" + +#: gtk_ardour/editor.cc:2313 +msgid "Bounce" +msgstr "Bounce" + +#: gtk_ardour/editor.cc:2323 +msgid "Lock" +msgstr "Verrouiller" + +#: gtk_ardour/editor.cc:2324 +msgid "Unlock" +msgstr "Déverrouiller" + +#: gtk_ardour/editor.cc:2334 +msgid "Original position" +msgstr "Position d'origine" + +#: gtk_ardour/editor.cc:2340 +msgid "Toggle envelope visibility" +msgstr "" + +#: gtk_ardour/editor.cc:2341 +#, fuzzy +msgid "Toggle envelope active" +msgstr "Activer" + +#: gtk_ardour/editor.cc:2345 +msgid "DeNormalize" +msgstr "Dénormaliser" + +#: gtk_ardour/editor.cc:2347 +msgid "Normalize" +msgstr "Normaliser" + +#: gtk_ardour/editor.cc:2350 +#, fuzzy +msgid "Reverse" +msgstr "Retourner" + +#: gtk_ardour/editor.cc:2359 +msgid "Nudge fwd" +msgstr "Décaler vers l'avant" + +#: gtk_ardour/editor.cc:2360 +#, fuzzy +msgid "Nudge bwd" +msgstr "Décaler vers l'arrière" + +#: gtk_ardour/editor.cc:2361 +msgid "Nudge fwd by capture offset" +msgstr "Décaler vers l'avant du décalage de la capture" + +#: gtk_ardour/editor.cc:2362 +msgid "Nudge bwd by capture offset" +msgstr "Décaler vers l'arrière du décallage de la capture" + +#: gtk_ardour/editor.cc:2371 +msgid "Start to edit cursor" +msgstr "Démarrer depuis le curseur d'édition" + +#: gtk_ardour/editor.cc:2372 +msgid "Edit cursor to end" +msgstr "Curseur d'édition à la fin" + +#: gtk_ardour/editor.cc:2374 +msgid "Trim" +msgstr "Élaguer" + +#: gtk_ardour/editor.cc:2377 +msgid "Split" +msgstr "Séparer" + +#: gtk_ardour/editor.cc:2380 +msgid "Make mono regions" +msgstr "Créer des régions mono" + +#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428 +msgid "Duplicate" +msgstr "Dupliquer" + +#: gtk_ardour/editor.cc:2384 +msgid "Fill Track" +msgstr "Remplir la piste" + +#: gtk_ardour/editor.cc:2388 +msgid "Destroy" +msgstr "Détruire" + +#: gtk_ardour/editor.cc:2418 +msgid "Play range" +msgstr "Jouer l'intervalle" + +#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446 +msgid "Loop range" +msgstr "Boucler sur l'intervalle" + +#: gtk_ardour/editor.cc:2421 +msgid "Create chunk from range" +msgstr "Nouveau fragment à partir de l'intervalle" + +#: gtk_ardour/editor.cc:2423 +msgid "Create Region" +msgstr "Créer une région" + +#: gtk_ardour/editor.cc:2424 +msgid "Separate Region" +msgstr "Séparer la région" + +#: gtk_ardour/editor.cc:2425 +msgid "Crop Region to range" +msgstr "Découper la région vers l'intervalle" + +#: gtk_ardour/editor.cc:2426 +#, fuzzy +msgid "Bounce range" +msgstr "Bounce intervalle" + +#: gtk_ardour/editor.cc:2432 +msgid "Fill range w/Region" +msgstr "Remplir l'intervalle avec une région" + +#: gtk_ardour/editor.cc:2434 +msgid "Range" +msgstr "Intervalle" + +#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538 +msgid "Play from edit cursor" +msgstr "Jouer à partir du curseur d'édition" + +#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539 +msgid "Play from start" +msgstr "Jouer depuis le début" + +#: gtk_ardour/editor.cc:2451 +msgid "Play region" +msgstr "Jouer la région" + +#: gtk_ardour/editor.cc:2453 +msgid "Loop Region" +msgstr "Boucler sur la région" + +#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540 +#: gtk_ardour/library_ui.cc:972 +msgid "Play" +msgstr "Jouer" + +#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548 +msgid "Select All in track" +msgstr "Tout sélectionner dans la piste" + +#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549 +msgid "Select All" +msgstr "Tout sélectionner" + +#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550 +msgid "Invert in track" +msgstr "Inverser dans la piste" + +#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551 +msgid "Invert" +msgstr "Inverser" + +#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553 +msgid "Select loop range" +msgstr "Sélectionner l'intervalle de boucle" + +#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554 +msgid "Select punch range" +msgstr "Sélectionner l'intervalle d'insertion" + +#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565 +#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369 +msgid "Cut" +msgstr "Couper" + +#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566 +#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371 +msgid "Copy" +msgstr "Copier" + +#: gtk_ardour/editor.cc:2482 +msgid "Paste at edit cursor" +msgstr "Coller au curseur d'édition" + +#: gtk_ardour/editor.cc:2483 +msgid "Paste at mouse" +msgstr "Coller au pointeur de la souris" + +#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923 +msgid "Align" +msgstr "Aligner" + +#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925 +msgid "Align Relative" +msgstr "Aligner relativement" + +#: gtk_ardour/editor.cc:2492 +msgid "Insert chunk" +msgstr "Insérer un fragment" + +#: gtk_ardour/editor.cc:2496 +msgid "New Region from range" +msgstr "Nouvelle région à partir de l'intervalle" + +#: gtk_ardour/editor.cc:2497 +#, fuzzy +msgid "Separate Range" +msgstr "Séparer l'intervalle" + +#: gtk_ardour/editor.cc:2507 +msgid "Insert Region" +msgstr "Insérer une région" + +#: gtk_ardour/editor.cc:2508 +msgid "Insert external sndfile" +msgstr "Insérer un fichier son externe" + +#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438 +msgid "Import" +msgstr "Importer" + +#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574 +msgid "Nudge entire track fwd" +msgstr "Décaler la piste entière en avant" + +#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575 +msgid "Nudge track after edit cursor fwd" +msgstr "Décaler la piste vers l'avant après le curseur d'édition" + +#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576 +msgid "Nudge entire track bwd" +msgstr "Décaler la piste entière vers l'arrière" + +#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577 +msgid "Nudge track after edit cursor bwd" +msgstr "Décaler la piste vers l'arrière après le curseur d'édition" + +#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920 +#: gtk_ardour/redirect_box.cc:373 +msgid "Paste" +msgstr "Coller" + +#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645 +#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799 +msgid "add marker" +msgstr "ajouter un marqueur" + +#: gtk_ardour/editor.cc:3084 +msgid "select/move objects" +msgstr "sélectionner/déplacer des objets" + +#: gtk_ardour/editor.cc:3085 +msgid "select/move ranges" +msgstr "sélectionner/déplacer des intervalles" + +#: gtk_ardour/editor.cc:3086 +msgid "draw gain automation" +msgstr "dessiner l'automatisation du gain" + +#: gtk_ardour/editor.cc:3087 +msgid "select zoom range" +msgstr "sélectionner la plage de zoom" + +#: gtk_ardour/editor.cc:3088 +msgid "stretch/shrink regions" +msgstr "étirer/rétrécir les régions" + +#: gtk_ardour/editor.cc:3089 +#, fuzzy +msgid "listen to specific regions" +msgstr "Écouter des régions spécifiques" + +#: gtk_ardour/editor.cc:3213 +msgid "Start:" +msgstr "Début :" + +#: gtk_ardour/editor.cc:3214 +msgid "End:" +msgstr "Fin :" + +#: gtk_ardour/editor.cc:3215 +msgid "Edit:" +msgstr "Éditer :" + +#: gtk_ardour/editor.cc:3429 +msgid "incorrectly formatted URI list, ignored" +msgstr "liste d'URI mal formattée, ignorée" + +#: gtk_ardour/editor.cc:3611 +#, fuzzy +msgid "set selected trackview" +msgstr "définir la vue de piste sélectionnée" + +#: gtk_ardour/editor.cc:3647 +#, fuzzy +msgid "set selected control point" +msgstr "Enlever le point de contrôle" + +#: gtk_ardour/editor.cc:3719 +#, fuzzy +msgid "set selected regionview" +msgstr "définir la vue de région sélectionnée" + +#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835 +#, fuzzy +msgid "set selected regions" +msgstr "définir les régions sélectionnées" + +#: gtk_ardour/editor.cc:3891 +msgid "Undo" +msgstr "Annuler" + +#: gtk_ardour/editor.cc:3893 +msgid "Undo (%1)" +msgstr "Annuler (%1)" + +#: gtk_ardour/editor.cc:3903 +msgid "Redo" +msgstr "Refaire" + +#: gtk_ardour/editor.cc:3905 +msgid "Redo (%1)" +msgstr "Refaire (%1)" + +#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946 +msgid "... as new track" +msgstr "" + +#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947 +#, fuzzy +msgid "... as new region" +msgstr "aligner la région" + +#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452 +msgid "Import audio (copy)" +msgstr "Importer audio (copie)" + +#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457 +msgid "Embed audio (link)" +msgstr "Incorporer audio (lien)" + +#: gtk_ardour/editor.cc:3953 +msgid "Remove last capture" +msgstr "Enlever la dernière capture" + +#: gtk_ardour/editor.cc:3974 +msgid "Duplicate how many times?" +msgstr "Dupliquer combien de fois ?" + +#: gtk_ardour/editor.cc:4550 +msgid "" +"Playlist %1 is currently unused.\n" +"If left alone, no audio files used by it will be cleaned.\n" +"If deleted, audio files used by it alone by will cleaned." +msgstr "" +"La liste de lecture %1 n'est pas utilisée.\n" +"Si vous la convervez, aucun fichier audio qu'elle utilise ne sera nettoyé.\n" +"Si vous l'effacez, les fichiers audio qu'elle seule utilise seront nettoyés." + +#: gtk_ardour/editor.cc:4555 +msgid "Delete playlist" +msgstr "Supprimer la playlist" + +#: gtk_ardour/editor.cc:4556 +msgid "Keep playlist" +msgstr "Garder la playlist" + +#: gtk_ardour/editor.cc:4557 +msgid "Cancel cleanup" +msgstr "Annuler le nettoyage" + +#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258 +#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290 +msgid "" +"programming error: control point canvas item has no control point object " +"pointer!" +msgstr "" +"erreur de programmation : point de contrôle de l'objet canvas sans pointeur " +"d'objet point de contrôle !" + +#: gtk_ardour/editor_canvas_events.cc:717 +msgid "programming error: line canvas item has no line object pointer!" +msgstr "" +"erreur de programmation : ligne de l'objet canvas sans pointeur d'objet " +"ligne !" + +#: gtk_ardour/editor_canvas_events.cc:744 +#: gtk_ardour/editor_canvas_events.cc:784 +#: gtk_ardour/editor_canvas_events.cc:823 +msgid "programming error: no \"rect\" pointer associated with selection item" +msgstr "" +"erreur de programmation : aucun pointeur \"rect\" n'est associé à l'object " +"sélection" + +#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298 +#: gtk_ardour/mixer_ui.cc:670 +msgid "Show All" +msgstr "Tout montrer" + +#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299 +#: gtk_ardour/mixer_ui.cc:671 +msgid "Hide All" +msgstr "Tout cacher" + +#: gtk_ardour/editor_edit_groups.cc:98 +msgid "Name for new edit group" +msgstr "Nom du nouveau groupe d'édition" + +#: gtk_ardour/editor_export_audio.cc:60 +msgid "" +"There is no range to export.\n" +"\n" +"Select a range using the range mouse mode" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707 +msgid "programming error: no ImageFrameView selected" +msgstr "erreur de programmation : aucun ImageFrameView selectionné" + +#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930 +msgid "programming error: no MarkerView selected" +msgstr "erreur de programmation : aucun MarkerView sélectionné" + +#: gtk_ardour/editor_keys.cc:187 +#, fuzzy +msgid "keyboard selection" +msgstr "étendre la sélection" + +#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376 +#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526 +#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584 +#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650 +#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700 +#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960 +#: gtk_ardour/editor_mouse.cc:4075 +msgid "programming error: marker canvas item has no marker object pointer!" +msgstr "" +"erreur de programmation : objet canvas de marqueur sans pointeur d'objet " +"marqueur !" + +#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681 +msgid "remove marker" +msgstr "enlever le marqueur" + +#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494 +#, fuzzy +msgid "Locate to" +msgstr "Locate to" + +#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495 +msgid "Play from" +msgstr "Jouer depuis" + +#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496 +msgid "Set from playhead" +msgstr "Jouer depuis la tête de lecture" + +#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497 +msgid "Set from range" +msgstr "Définir à partir de l'intervalle" + +#: gtk_ardour/editor_markers.cc:479 +msgid "Set Loop Range" +msgstr "Définir l'intervalle de boucle" + +#: gtk_ardour/editor_markers.cc:480 +msgid "Set Punch Range" +msgstr "Définir l'intervalle d'insertion" + +#: gtk_ardour/editor_markers.cc:736 +msgid "ardour: rename mark" +msgstr "ardour : renommer le marqueur" + +#: gtk_ardour/editor_markers.cc:738 +msgid "ardour: rename range" +msgstr "ardour : renommer l'intervalle" + +#: gtk_ardour/editor_markers.cc:792 +msgid "set loop range" +msgstr "définir l'intervalle de boucle" + +#: gtk_ardour/editor_markers.cc:818 +msgid "set punch range" +msgstr "définir l'intervalle d'insertion" + +#: gtk_ardour/editor_mouse.cc:99 +msgid "Editor::event_frame() used on unhandled event type %1" +msgstr "Editor::event_frame() utilisé sur un évènement non géré de type %1" + +#: gtk_ardour/editor_mouse.cc:1555 +msgid "programming error: start_grab called without drag item" +msgstr "erreur de programmation : start_grab appelé sans objet a ramasser" + +#: gtk_ardour/editor_mouse.cc:1760 +msgid "change fade in length" +msgstr "modifier la longueur du fondu d'ouverture" + +#: gtk_ardour/editor_mouse.cc:1778 +#, fuzzy +msgid "programming error: fade out canvas item has no regionview data pointer!" +msgstr "" +"programming error: fade out canvas item has no regionview data pointer!" + +#: gtk_ardour/editor_mouse.cc:1852 +msgid "change fade out length" +msgstr "modifier la longueur du fondu de fermeture" + +#: gtk_ardour/editor_mouse.cc:1871 +msgid "programming error: cursor canvas item has no cursor data pointer!" +msgstr "" +"erreur de programmation : objet canvas de curseur sans pointeur de données " +"curseur" + +#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470 +msgid "" +"programming error: meter marker canvas item has no marker object pointer!" +msgstr "" +"erreur de programmation: meter marker canvas item has no marker object " +"pointer!" + +#: gtk_ardour/editor_mouse.cc:2163 +msgid "move meter mark" +msgstr "déplacer le marqueur de vu-mètre" + +#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335 +#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439 +msgid "" +"programming error: tempo marker canvas item has no marker object pointer!" +msgstr "" +"erreur de programmation : objet canvas de marqueur de tempo sans pointeur " +"d'objet marqueur !" + +#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340 +#: gtk_ardour/editor_tempodisplay.cc:425 +msgid "programming error: marker for tempo is not a tempo marker!" +msgstr "" +"erreur de programmation : le marqueur du tempo n'est pas un marqueur de " +"tempo !" + +#: gtk_ardour/editor_mouse.cc:2245 +msgid "move tempo mark" +msgstr "déplacer le marqueur de tempo" + +#: gtk_ardour/editor_mouse.cc:2388 +msgid "programming error: line canvas item has no line pointer!" +msgstr "" +"erreur de programmation : objet canvas de ligne sans pointeur de ligne !" + +#: gtk_ardour/editor_mouse.cc:2497 +#, fuzzy +msgid "move region(s)" +msgstr "enlever la région" + +#: gtk_ardour/editor_mouse.cc:2509 +msgid "Drag region copy" +msgstr "Déplacer la copie de la région" + +#: gtk_ardour/editor_mouse.cc:2579 +#, fuzzy +msgid "copy region(s)" +msgstr "Déplacer la/les région(s)" + +#: gtk_ardour/editor_mouse.cc:2612 +#, fuzzy +msgid "Drag region brush" +msgstr "Déplacer la/les région(s)" + +#: gtk_ardour/editor_mouse.cc:3425 +#, fuzzy +msgid "selection grab" +msgstr "attraper la sélection" + +#: gtk_ardour/editor_mouse.cc:3571 +msgid "range selection" +msgstr "sélection d'intervalle" + +#: gtk_ardour/editor_mouse.cc:3587 +msgid "trim selection start" +msgstr "élaguer le début de la sélection" + +#: gtk_ardour/editor_mouse.cc:3603 +msgid "trim selection end" +msgstr "élaguer la fin de la sélection" + +#: gtk_ardour/editor_mouse.cc:3620 +msgid "move selection" +msgstr "déplacer la sélection" + +#: gtk_ardour/editor_mouse.cc:3995 +msgid "Start point trim" +msgstr "Point de départ d'élaguage" + +#: gtk_ardour/editor_mouse.cc:4023 +msgid "End point trim" +msgstr "Point de fin d'élaguage" + +#: gtk_ardour/editor_mouse.cc:4062 +msgid "trimmed region" +msgstr "région élaguée" + +#: gtk_ardour/editor_mouse.cc:4203 +msgid "new range marker" +msgstr "nouveau marqueur d'intervalle" + +#: gtk_ardour/editor_mouse.cc:4422 +msgid "select regions" +msgstr "sélectionner les régions" + +#: gtk_ardour/editor_mouse.cc:4451 +msgid "Name for region:" +msgstr "Nom de la région :" + +#: gtk_ardour/editor_mouse.cc:4517 +msgid "timestretch" +msgstr "déformation temporelle" + +#: gtk_ardour/editor_ops.cc:117 +msgid "split" +msgstr "séparer" + +#: gtk_ardour/editor_ops.cc:153 +msgid "remove region" +msgstr "enlever la région" + +#: gtk_ardour/editor_ops.cc:172 +msgid "" +" This is destructive, will possibly delete audio files\n" +"It cannot be undone\n" +"Do you really want to destroy %1 ?" +msgstr "" +" Ceci est destructif, et effacera peut-être des fichiers audio\n" +"Cela ne pourra être annulé\n" +"Voulez-vous vraiment détruire %1 ?" + +#: gtk_ardour/editor_ops.cc:176 +msgid "these regions" +msgstr "ces régions" + +#: gtk_ardour/editor_ops.cc:176 +msgid "this region" +msgstr "cette région" + +#: gtk_ardour/editor_ops.cc:179 +msgid "Yes, destroy them." +msgstr "Oui, les détruire." + +#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434 +msgid "Yes, destroy it." +msgstr "Oui, la supprimer." + +#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435 +#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300 +msgid "No, do nothing." +msgstr "Non, ne rien faire." + +#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307 +msgid "extend selection" +msgstr "étendre la sélection" + +#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357 +#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427 +msgid "nudge forward" +msgstr "décaler vers l'avant" + +#: gtk_ardour/editor_ops.cc:491 +msgid "build_region_boundary_cache called with snap_type = %1" +msgstr "build_region_boundary_cache appelé avec snap_type = %1" + +#: gtk_ardour/editor_ops.cc:1305 +msgid "set selection from range" +msgstr "définir la sélection à partir de l'intervalle" + +#: gtk_ardour/editor_ops.cc:1421 +msgid "clear markers" +msgstr "effacer les marqueurs" + +#: gtk_ardour/editor_ops.cc:1433 +msgid "clear ranges" +msgstr "effacer les intervalles" + +#: gtk_ardour/editor_ops.cc:1452 +msgid "clear locations" +msgstr "effacer les emplacements" + +#: gtk_ardour/editor_ops.cc:1503 +msgid "insert dragged region" +msgstr "insérer la région déplacée" + +#: gtk_ardour/editor_ops.cc:1538 +msgid "insert region" +msgstr "insérer une région" + +#: gtk_ardour/editor_ops.cc:1744 +msgid "ardour: rename region" +msgstr "ardour : renommer la région" + +#: gtk_ardour/editor_ops.cc:1891 +msgid "You can't import an audiofile until you have a session loaded." +msgstr "" +"Vous ne pouvez pas importer un fichier audio avant d'avoir chargé une " +"session." + +#: gtk_ardour/editor_ops.cc:1901 +#, fuzzy +msgid "Import selected as tracks" +msgstr "Import sélectionné" + +#: gtk_ardour/editor_ops.cc:1904 +#, fuzzy +msgid "Import selected to region list" +msgstr "définir les régions sélectionnées" + +#: gtk_ardour/editor_ops.cc:1933 +msgid "ardour: audio import in progress" +msgstr "ardour : importation audio en cours" + +#: gtk_ardour/editor_ops.cc:1937 +msgid "Cancel Import" +msgstr "Annuler l'importation" + +#: gtk_ardour/editor_ops.cc:1944 +msgid "ardour: importing %1" +msgstr "ardour : importation de %1" + +#: gtk_ardour/editor_ops.cc:1990 +msgid "%1 it anyway" +msgstr "le %1 quand même" + +#: gtk_ardour/editor_ops.cc:1996 +#, fuzzy +msgid "Don't %1 it" +msgstr "Ne pas %1" + +#: gtk_ardour/editor_ops.cc:1997 +msgid "%1 all without questions" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1998 +#, fuzzy +msgid "Cancel entire import" +msgstr "Annuler l'importation" + +#: gtk_ardour/editor_ops.cc:2004 +msgid "" +"%1\n" +"This audiofile's sample rate doesn't match the session sample rate!" +msgstr "" +"%1\n" +"La fréquence d'échantillonage de ce fichier audio ne correspond pas à celle " +"de la session !" + +#: gtk_ardour/editor_ops.cc:2032 +msgid "You can't embed an audiofile until you have a session loaded." +msgstr "" +"Vous ne pouvez pas incorporer un fichier audio avant d'avoir chargé une " +"session." + +#: gtk_ardour/editor_ops.cc:2039 +msgid "Add to External Region list" +msgstr "Ajouter à la liste des régions externes" + +#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210 +#: gtk_ardour/editor_ops.cc:2286 +msgid "Editor: cannot open file \"%1\" (%2)" +msgstr "Éditeur : impossible d'ouvrir le fichier \"%1\" (%2)" + +#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312 +msgid "could not open %1" +msgstr "impossible d'ouvrir %1" + +#: gtk_ardour/editor_ops.cc:2171 +#, fuzzy +msgid "Insert selected as new tracks" +msgstr "définir la vue de piste sélectionnée" + +#: gtk_ardour/editor_ops.cc:2186 +msgid "Insert selected" +msgstr "Insertion sélectionnée" + +#: gtk_ardour/editor_ops.cc:2327 +msgid "insert sndfile" +msgstr "Insérer un fichier son" + +#: gtk_ardour/editor_ops.cc:2464 +msgid "separate" +msgstr "séparer" + +#: gtk_ardour/editor_ops.cc:2528 +msgid "trim to selection" +msgstr "élaguer selon la sélection" + +#: gtk_ardour/editor_ops.cc:2568 +msgid "region fill" +msgstr "remplissage de la région" + +#: gtk_ardour/editor_ops.cc:2626 +msgid "fill selection" +msgstr "remplir la sélection" + +#: gtk_ardour/editor_ops.cc:2650 +msgid "Place the edit cursor at the desired sync point" +msgstr "Placer le curseur d'édition au point de synchro. désiré" + +#: gtk_ardour/editor_ops.cc:2656 +msgid "set sync from edit cursor" +msgstr "définir la synchro. au curseur d'édition" + +#: gtk_ardour/editor_ops.cc:2668 +msgid "remove sync" +msgstr "enlever la synchro." + +#: gtk_ardour/editor_ops.cc:2682 +msgid "naturalize" +msgstr "normaliser" + +#: gtk_ardour/editor_ops.cc:2746 +msgid "align selection (relative)" +msgstr "Aligner la sélection (relativement)" + +#: gtk_ardour/editor_ops.cc:2774 +msgid "align selection" +msgstr "aligner la sélection" + +#: gtk_ardour/editor_ops.cc:2786 +msgid "align region" +msgstr "aligner la région" + +#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858 +#, fuzzy +msgid "trim to edit" +msgstr "élaguer to edit" + +#: gtk_ardour/editor_ops.cc:2909 +#, fuzzy +msgid "ardour: freeze" +msgstr "ardour :" + +#: gtk_ardour/editor_ops.cc:2914 +#, fuzzy +msgid "Cancel Freeze" +msgstr "Annuler" + +#: gtk_ardour/editor_ops.cc:2951 +#, fuzzy +msgid "bounce range" +msgstr "bounce intervalle" + +#: gtk_ardour/editor_ops.cc:3004 +msgid "cut" +msgstr "couper" + +#: gtk_ardour/editor_ops.cc:3007 +msgid "copy" +msgstr "copier" + +#: gtk_ardour/editor_ops.cc:3020 +msgid " objects" +msgstr " objets" + +#: gtk_ardour/editor_ops.cc:3046 +msgid " range" +msgstr " intervalle" + +#: gtk_ardour/editor_ops.cc:3201 +msgid "paste" +msgstr "coller" + +#: gtk_ardour/editor_ops.cc:3236 +msgid "paste chunk" +msgstr "coller le fragment" + +#: gtk_ardour/editor_ops.cc:3276 +msgid "duplicate region" +msgstr "dupliquer la région" + +#: gtk_ardour/editor_ops.cc:3309 +msgid "duplicate selection" +msgstr "dupliquer la sélection" + +#: gtk_ardour/editor_ops.cc:3349 +msgid "clear playlist" +msgstr "effacer la liste de lecture" + +#: gtk_ardour/editor_ops.cc:3378 +msgid "nudge track" +msgstr "décaler la piste" + +#: gtk_ardour/editor_ops.cc:3431 +msgid "" +"Do you really want to destroy the last capture?\n" +"(This is destructive and cannot be undone)" +msgstr "" +"Voulez-vous vraiment supprimer la dernière capture ?\n" +"(cette opération est destructive et ne pourra pas être annulée)" + +#: gtk_ardour/editor_ops.cc:3463 +msgid "normalize" +msgstr "normaliser" + +#: gtk_ardour/editor_ops.cc:3510 +msgid "reverse regions" +msgstr "inverser les régions" + +#: gtk_ardour/editor_region_list.cc:223 +msgid "hidden" +msgstr "caché" + +#: gtk_ardour/editor_region_list.cc:408 +msgid "Show all" +msgstr "Tout montrer" + +#: gtk_ardour/editor_region_list.cc:417 +msgid "Ascending" +msgstr "Montant" + +#: gtk_ardour/editor_region_list.cc:419 +msgid "Descending" +msgstr "Descendant" + +#: gtk_ardour/editor_region_list.cc:423 +msgid "By Region Name" +msgstr "Par nom de région" + +#: gtk_ardour/editor_region_list.cc:425 +msgid "By Region Length" +msgstr "Par longueur de région" + +#: gtk_ardour/editor_region_list.cc:427 +msgid "By Region Position" +msgstr "Par position de région" + +#: gtk_ardour/editor_region_list.cc:429 +msgid "By Region Timestamp" +msgstr "Par date de région" + +#: gtk_ardour/editor_region_list.cc:431 +msgid "By Region Start in File" +msgstr "Par début de région dans le fichier" + +#: gtk_ardour/editor_region_list.cc:433 +msgid "By Region End in File" +msgstr "Par fin de région dans le fichier" + +#: gtk_ardour/editor_region_list.cc:435 +msgid "By Source File Name" +msgstr "Par nom de fichier source" + +#: gtk_ardour/editor_region_list.cc:437 +msgid "By Source File Length" +msgstr "Par longueur de fichier source" + +#: gtk_ardour/editor_region_list.cc:439 +msgid "By Source File Creation Date" +msgstr "Par date de création du fichier source" + +#: gtk_ardour/editor_region_list.cc:441 +msgid "By Source Filesystem" +msgstr "Par système de fichier source" + +#: gtk_ardour/editor_region_list.cc:444 +msgid "Sorting" +msgstr "Tri" + +#: gtk_ardour/editor_region_list.cc:808 +msgid "Regions/length" +msgstr "Région/longueur" + +#: gtk_ardour/editor_region_list.cc:812 +msgid "Regions/position" +msgstr "Régions/position" + +#: gtk_ardour/editor_region_list.cc:816 +msgid "Regions/creation" +msgstr "Régions/création" + +#: gtk_ardour/editor_region_list.cc:820 +msgid "Regions/start" +msgstr "Régions/début" + +#: gtk_ardour/editor_region_list.cc:824 +msgid "Regions/end" +msgstr "Régions/fin" + +#: gtk_ardour/editor_region_list.cc:828 +msgid "Regions/file name" +msgstr "Régions/nom de fichier" + +#: gtk_ardour/editor_region_list.cc:832 +msgid "Regions/file size" +msgstr "Régions/taille de fichier" + +#: gtk_ardour/editor_region_list.cc:836 +msgid "Regions/file date" +msgstr "Région/date de fichier" + +#: gtk_ardour/editor_region_list.cc:840 +msgid "Regions/file system" +msgstr "Région/système de fichier" + +#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73 +#: gtk_ardour/editor_route_list.cc:231 +msgid "editor" +msgstr "éditeur" + +#: gtk_ardour/editor_route_list.cc:300 +msgid "Show All AbstractTracks" +msgstr "Montrer toutes les PistesAbstraites" + +#: gtk_ardour/editor_route_list.cc:301 +msgid "Hide All AbstractTracks" +msgstr "Cacher toutes les PistesAbstraites" + +#: gtk_ardour/editor_route_list.cc:302 +msgid "Show All AudioBus" +msgstr "Montrer tous les BusAudio" + +#: gtk_ardour/editor_route_list.cc:303 +msgid "Hide All AudioBus" +msgstr "Cacher tous les BusAudio" + +#: gtk_ardour/editor_rulers.cc:311 +msgid "New location marker" +msgstr "Nouveau marqueur d'emplacement" + +#: gtk_ardour/editor_rulers.cc:312 +msgid "Clear all locations" +msgstr "Effacer tous les emplacements" + +#: gtk_ardour/editor_rulers.cc:317 +msgid "Clear all ranges" +msgstr "Effacer tous les intervalles" + +#: gtk_ardour/editor_rulers.cc:326 +msgid "New Tempo" +msgstr "Nouveau tempo" + +#: gtk_ardour/editor_rulers.cc:327 +msgid "Clear tempo" +msgstr "Effacer le tempo" + +#: gtk_ardour/editor_rulers.cc:332 +msgid "New Meter" +msgstr "Nouveau vu-mètre" + +#: gtk_ardour/editor_rulers.cc:333 +msgid "Clear meter" +msgstr "Effacer les vu-mètre" + +#: gtk_ardour/editor_rulers.cc:341 +msgid "Min:Secs" +msgstr "Mins:Secs" + +#: gtk_ardour/editor_selection_list.cc:117 +msgid "name for chunk:" +msgstr "nom du fragment :" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Create chunk" +msgstr "Créer un fragment" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Forget it" +msgstr "Oublier" + +#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295 +msgid "add" +msgstr "ajouter" + +#: gtk_ardour/editor_tempodisplay.cc:276 +msgid "add tempo mark" +msgstr "ajouter un marqueur de tempo" + +#: gtk_ardour/editor_tempodisplay.cc:318 +msgid "add meter mark" +msgstr "ajouter un marqueur de vu-mètre" + +#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383 +msgid "done" +msgstr "terminé" + +#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404 +msgid "replace tempo mark" +msgstr "remplacer le marqueur de tempo" + +#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475 +msgid "programming error: marker for meter is not a meter marker!" +msgstr "erreur de programmation : marker for meter is not a meter marker!" + +#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487 +msgid "remove tempo mark" +msgstr "enlever le marqueur de tempo" + +#: gtk_ardour/editor_timefx.cc:50 +msgid "Quick but Ugly" +msgstr "Rapide mais sale" + +#: gtk_ardour/editor_timefx.cc:51 +msgid "Skip Anti-aliasing" +msgstr "Sauter l'anti-crénelage" + +#: gtk_ardour/editor_timefx.cc:53 +msgid "Stretch/Shrink it" +msgstr "Étirer/Rétrécir" + +#: gtk_ardour/editor_timefx.cc:57 +msgid "ardour: timestretch" +msgstr "ardour : déformation temporelle" + +#: gtk_ardour/editor_timefx.cc:58 +msgid "TimeStretchDialog" +msgstr "TimeStretchDialog" + +#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83 +#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85 +msgid "TimeStretchButton" +msgstr "TimeStretchButton" + +#: gtk_ardour/editor_timefx.cc:86 +msgid "TimeStretchProgress" +msgstr "TimeStretchProgress" + +#: gtk_ardour/editor_timefx.cc:151 +msgid "timestretch cannot be started - thread creation error" +msgstr "" + +#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410 +#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189 +msgid "22.05kHz" +msgstr "22.05 kHz" + +#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413 +#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949 +#: gtk_ardour/export_dialog.cc:1191 +msgid "44.1kHz" +msgstr "44.1 kHz" + +#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416 +#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193 +msgid "48kHz" +msgstr "48 kHz" + +#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419 +#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195 +msgid "88.2kHz" +msgstr "88.2 kHz" + +#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422 +#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197 +msgid "96kHz" +msgstr "96 kHz" + +#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425 +#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199 +msgid "192kHz" +msgstr "192 kHz" + +#: gtk_ardour/export_dialog.cc:73 +msgid "best" +msgstr "meilleur" + +#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964 +msgid "fastest" +msgstr "rapide" + +#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966 +msgid "linear" +msgstr "linéaire" + +#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968 +msgid "better" +msgstr "meilleur" + +#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970 +msgid "intermediate" +msgstr "intermédiaire" + +#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979 +msgid "Rectangular" +msgstr "Rectangulaire" + +#: gtk_ardour/export_dialog.cc:84 +msgid "Shaped Noise" +msgstr "Shaped noise" + +#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981 +msgid "Triangular" +msgstr "Triangulaire" + +#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336 +msgid "stereo" +msgstr "stéréo" + +#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497 +#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219 +#: gtk_ardour/utils.cc:334 +msgid "mono" +msgstr "mono" + +#: gtk_ardour/export_dialog.cc:97 +msgid "CUE" +msgstr "CUE" + +#: gtk_ardour/export_dialog.cc:98 +msgid "TOC" +msgstr "TOC" + +#: gtk_ardour/export_dialog.cc:106 +msgid "FORMAT" +msgstr "FORMAT" + +#: gtk_ardour/export_dialog.cc:107 +msgid "SAMPLE RATE" +msgstr "VITESSE D'ÉCHANTILLONAGE" + +#: gtk_ardour/export_dialog.cc:108 +msgid "CONVERSION QUALITY" +msgstr "QUALITÉ DE LA CONVERSION" + +#: gtk_ardour/export_dialog.cc:109 +msgid "DITHER TYPE" +msgstr "TYPE D'INTERPOLATION" + +#: gtk_ardour/export_dialog.cc:110 +#, fuzzy +msgid "CD MARKER FILE TYPE" +msgstr "TYPE DE FICHIER DU MARQUEUR DE CD" + +#: gtk_ardour/export_dialog.cc:111 +msgid "CHANNELS" +msgstr "VOIES" + +#: gtk_ardour/export_dialog.cc:112 +msgid "FILE TYPE" +msgstr "TYPE DE FICHIER" + +#: gtk_ardour/export_dialog.cc:113 +msgid "SAMPLE FORMAT" +msgstr "FORMAT D'ÉCHANTILLON" + +#: gtk_ardour/export_dialog.cc:114 +msgid "SAMPLE ENDIANNESS" +msgstr "ENDIANNESS DES ÉCHANTILLONS" + +#: gtk_ardour/export_dialog.cc:115 +#, fuzzy +msgid "EXPORT CD MARKER FILE ONLY" +msgstr "EXPORTER SEULEMENT LE FICHIER DE MARQUEUR DE CD" + +#: gtk_ardour/export_dialog.cc:116 +msgid "EXPORT TO FILE" +msgstr "EXPORTER VERS FICHIER" + +#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118 +#: gtk_ardour/option_editor.cc:119 +msgid "Browse" +msgstr "Parcourir" + +#: gtk_ardour/export_dialog.cc:119 +msgid "Specific tracks ..." +msgstr "Pistes spécifiques..." + +#: gtk_ardour/export_dialog.cc:131 +msgid "ardour: export" +msgstr "ardour : exporter" + +#: gtk_ardour/export_dialog.cc:132 +msgid "ardour_export" +msgstr "ardour_exporter" + +#: gtk_ardour/export_dialog.cc:156 +msgid "Output" +msgstr "Sortie" + +#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626 +msgid "Track" +msgstr "Piste" + +#: gtk_ardour/export_dialog.cc:287 +msgid "slereg" +msgstr "slereg" + +#: gtk_ardour/export_dialog.cc:658 +msgid "Editor: cannot open \"%1\" as export file for CD toc file" +msgstr "" +"Editeur : impossible d'ouvrir \"%1\" comme fichier de table des matières de " +"CD" + +#: gtk_ardour/export_dialog.cc:780 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD cue file" +msgstr "" +"Editeur : impossible d'ouvrir \"%1\" comme fichier d'exportation de marqueur " +"de piste CD" + +#: gtk_ardour/export_dialog.cc:799 +msgid "WAV" +msgstr "WAV" + +#: gtk_ardour/export_dialog.cc:1051 +msgid "Stop Export" +msgstr "Arrêter l'exportation" + +#: gtk_ardour/gain_automation_time_axis.cc:60 +#, fuzzy +msgid "add gain automation event" +msgstr "ajouter les évènements d'automatisation à " + +#: gtk_ardour/gain_meter.cc:68 +msgid "Cannot create slider pixmaps" +msgstr "" + +#: gtk_ardour/gain_meter.cc:83 +msgid "dbFS" +msgstr "" + +#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134 +#: gtk_ardour/gain_meter.cc:728 +msgid "pre" +msgstr "" + +#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724 +#, fuzzy +msgid "input" +msgstr "entrée %1" + +#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732 +#, fuzzy +msgid "post" +msgstr "port" + +#: gtk_ardour/gain_meter.cc:146 +msgid "tupni" +msgstr "" + +#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470 +#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537 +#, fuzzy +msgid "-inf" +msgstr "entrée" + +#: gtk_ardour/imageframe_socket_handler.cc:127 +msgid "Image Compositor Socket has been shutdown/closed" +msgstr "La socket du compositeur d'image a été arrêtée/fermée" + +#: gtk_ardour/imageframe_time_axis.cc:295 +msgid "0.5 seconds" +msgstr "0.5 secondes" + +#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259 +msgid "1 seconds" +msgstr "1 seconde" + +#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260 +msgid "1.5 seconds" +msgstr "1.5 secondes" + +#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261 +msgid "2 seconds" +msgstr "2 secondes" + +#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262 +msgid "2.5 seconds" +msgstr "2.5 secondes" + +#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263 +msgid "3 seconds" +msgstr "3 secondes" + +#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268 +msgid "Duration (sec)" +msgstr "Durée (s)" + +#: gtk_ardour/imageframe_time_axis.cc:310 +msgid "Remove Frame" +msgstr "Enlever une trame" + +#: gtk_ardour/imageframe_time_axis.cc:313 +msgid "Image Frame" +msgstr "Trame d'image" + +#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274 +msgid "Rename Track" +msgstr "Renommer la piste" + +#: gtk_ardour/io_selector.cc:64 +msgid "%1 input" +msgstr "entrée %1" + +#: gtk_ardour/io_selector.cc:66 +msgid "%1 output" +msgstr "sortie %1" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103 +msgid "Inputs" +msgstr "Entrées" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104 +msgid "Outputs" +msgstr "Sorties" + +#: gtk_ardour/io_selector.cc:142 +msgid "Add Input" +msgstr "Ajouter une entrée" + +#: gtk_ardour/io_selector.cc:142 +msgid "Add Output" +msgstr "Ajouter une sortie" + +#: gtk_ardour/io_selector.cc:143 +msgid "Remove Input" +msgstr "Enlever une entrée" + +#: gtk_ardour/io_selector.cc:143 +msgid "Remove Output" +msgstr "Enlever une sortie" + +#: gtk_ardour/io_selector.cc:144 +msgid "Disconnect All" +msgstr "Déconnecter tout" + +#: gtk_ardour/io_selector.cc:158 +msgid "Available connections" +msgstr "Connexions disponibles" + +#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636 +#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724 +msgid "port" +msgstr "port" + +#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587 +msgid "There are no more JACK ports available." +msgstr "Il n'y a plus de ports JACK disponibles" + +#: gtk_ardour/io_selector.cc:790 +msgid "ardour: " +msgstr "ardour :" + +#: gtk_ardour/keyboard.cc:419 +msgid "KeyboardTarget: keyname \"%1\" is unknown." +msgstr "KeyboardTarget : nom de touche \"%1\" inconnue" + +#: gtk_ardour/keyboard.cc:645 +msgid "" +"Your system is completely broken - NumLock uses \"%1\"as its modifier. This " +"is madness - see the man page for xmodmap to find out how to fix this." +msgstr "" +"Votre système débloque complétement -- la touche de verrouillage numérique " +"utilise \"%1\" comme modificateur. C'est n'importe quoi -- consultez la page " +"de manuel de xmodmap pour trouver comment réparer ça." + +#: gtk_ardour/keyboard.cc:653 +msgid "" +"Your system generates \"%1\" when the NumLock key is pressed. This can cause " +"problems when editing so Ardour will use %2 to mean Meta rather than %1" +msgstr "" +"Votre système génère \"%1\" quand la touche de verrouillage numérique est " +"pressée. Cela peut causer des problèmes pendant l'édition, aussi Ardour " +"utilisera %2 comme touche Meta plutôt que %1" + +#: gtk_ardour/keyboard.cc:714 +msgid "You have %1 keys bound to \"mod1\"" +msgstr "Vous avez %1 touches affectées à \"mod1\"" + +#: gtk_ardour/keyboard.cc:729 +msgid "You have %1 keys bound to \"mod2\"" +msgstr "Vous avez %1 touches affectées à \"mod2\"" + +#: gtk_ardour/keyboard.cc:744 +msgid "You have %1 keys bound to \"mod3\"" +msgstr "Vous avez %1 touches affectées à \"mod3\"" + +#: gtk_ardour/keyboard.cc:759 +msgid "You have %1 keys bound to \"mod4\"" +msgstr "Vous avez %1 touches affectées à \"mod4\"" + +#: gtk_ardour/keyboard.cc:774 +msgid "You have %1 keys bound to \"mod5\"" +msgstr "Vous avez %1 touches affectées à \"mod5\"" + +#: gtk_ardour/keyboard_target.cc:72 +msgid "KeyboardTarget: empty string passed to add_binding." +msgstr "" + +#: gtk_ardour/keyboard_target.cc:78 +msgid "KeyboardTarget: no translation found for \"%1\"" +msgstr "KeyboardTarget : aucune traduction trouvée pour \"%1\"" + +#: gtk_ardour/keyboard_target.cc:83 +msgid "KeyboardTarget: unknown action \"%1\"" +msgstr "KeyboardTarget : action \"%1\" inconnue" + +#: gtk_ardour/keyboard_target.cc:248 +msgid "misformed binding node - ignored" +msgstr "misformed binding node -- ignored" + +#: gtk_ardour/library_ui.cc:62 +#, fuzzy +msgid "Soundfile Library" +msgstr "Bibliothèque audio" + +#: gtk_ardour/library_ui.cc:63 +msgid "Filesystem" +msgstr "Système de fichier" + +#: gtk_ardour/library_ui.cc:66 +msgid "Split Channels" +msgstr "Séparer les voies" + +#: gtk_ardour/library_ui.cc:69 +msgid "ardour: soundfile selector" +msgstr "ardour : sélection de fichier son" + +#: gtk_ardour/library_ui.cc:430 +msgid "Add to Library..." +msgstr "Ajouter à la bibliothèque..." + +#: gtk_ardour/library_ui.cc:431 +msgid "Remove..." +msgstr "Enlever..." + +#: gtk_ardour/library_ui.cc:432 +msgid "Find..." +msgstr "Chercher..." + +#: gtk_ardour/library_ui.cc:433 +msgid "Add Folder" +msgstr "Ajouter un dossier" + +#: gtk_ardour/library_ui.cc:434 +msgid "Add audio file or directory" +msgstr "Ajouter un fichier ou un dossier" + +#: gtk_ardour/library_ui.cc:713 +msgid "Importing" +msgstr "Importation en cours" + +#: gtk_ardour/library_ui.cc:748 +msgid "%1 not added to database" +msgstr "%1 n'a pas été ajouté à la base de données" + +#: gtk_ardour/library_ui.cc:767 +msgid "Folder name:" +msgstr "Nom du dossier :" + +#: gtk_ardour/library_ui.cc:838 +msgid "Should not be reached" +msgstr "Ne devrait pas être atteint" + +#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096 +msgid "file \"%1\" could not be opened" +msgstr "le fichier \"%1\" n'a pu être ouvert" + +#: gtk_ardour/library_ui.cc:956 +msgid "Field" +msgstr "Champ" + +#: gtk_ardour/library_ui.cc:957 +msgid "Value" +msgstr "Valeur" + +#: gtk_ardour/library_ui.cc:973 +msgid "Stop" +msgstr "Arrêter" + +#: gtk_ardour/library_ui.cc:974 +msgid "Add Field..." +msgstr "Ajouter un champ..." + +#: gtk_ardour/library_ui.cc:975 +msgid "Remove Field" +msgstr "Enlever un champ" + +#: gtk_ardour/library_ui.cc:979 +msgid "Soundfile Info" +msgstr "Information du fichier son" + +#: gtk_ardour/library_ui.cc:1106 +msgid "file \"%1\" appears not to be an audio file" +msgstr "le fichier \"%1\" ne semble pas être un fichier audio" + +#: gtk_ardour/library_ui.cc:1159 +msgid "Could not read file: %1 (%2)." +msgstr "Impossible delire le fichier %1 (%2)." + +#: gtk_ardour/library_ui.cc:1177 +msgid "Could not access soundfile: " +msgstr "Impossible d'accéder au fichier son : " + +#: gtk_ardour/library_ui.cc:1222 +msgid "Field name:" +msgstr "Nom de champ :" + +#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367 +msgid "Field value:" +msgstr "Valeur du champ :" + +#: gtk_ardour/library_ui.cc:1295 +msgid "Find" +msgstr "Trouver" + +#: gtk_ardour/library_ui.cc:1296 +msgid "AND" +msgstr "ET" + +#: gtk_ardour/library_ui.cc:1297 +msgid "OR" +msgstr "OU" + +#: gtk_ardour/library_ui.cc:1300 +msgid "ardour: locate soundfiles" +msgstr "ardour : trouver fichiers audio" + +#: gtk_ardour/library_ui.cc:1426 +msgid "Results" +msgstr "Résultats" + +#: gtk_ardour/library_ui.cc:1427 +msgid "Uris" +msgstr "Uris" + +#: gtk_ardour/library_ui.cc:1439 +msgid "Create multi-channel region" +msgstr "Créer une région multi-voie" + +#: gtk_ardour/library_ui.cc:1442 +msgid "Ardour: Search Results" +msgstr "Ardour : résultat de la recherche" + +#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50 +msgid "Set" +msgstr "Définir" + +#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51 +msgid "Go" +msgstr "Aller" + +#: gtk_ardour/location_ui.cc:54 +msgid "CD" +msgstr "CD" + +#: gtk_ardour/location_ui.cc:55 +msgid "Hidden" +msgstr "Caché" + +#: gtk_ardour/location_ui.cc:57 +msgid "SCMS" +msgstr "SCMS" + +#: gtk_ardour/location_ui.cc:58 +msgid "Pre-Emphasis" +msgstr "Pré-emphase" + +#: gtk_ardour/location_ui.cc:592 +msgid "Add New Location" +msgstr "Ajouter un nouvel emplacement" + +#: gtk_ardour/location_ui.cc:593 +msgid "Add New Range" +msgstr "Ajouter un nouvel intervalle" + +#: gtk_ardour/location_ui.cc:597 +msgid "ardour: locations" +msgstr "ardour : emplacements" + +#: gtk_ardour/location_ui.cc:598 +msgid "ardour_locations" +msgstr "ardour_emplacements" + +#: gtk_ardour/location_ui.cc:629 +#, fuzzy +msgid "Location (CD Index) Markers" +msgstr "Marqueurs d'emplacements (Index de CD)" + +#: gtk_ardour/location_ui.cc:649 +#, fuzzy +msgid "Range (CD Track) Markers" +msgstr "Marqueurs d'intervalles (Piste de CD)" + +#: gtk_ardour/location_ui.cc:814 +msgid "add range marker" +msgstr "ajouter marqueur d'intervalle" + +#: gtk_ardour/main.cc:76 +msgid "ardour is killing itself for a clean exit\n" +msgstr "ardour se termine lui-même pour une sortie propre\n" + +#: gtk_ardour/main.cc:85 +msgid "stopping user interface\n" +msgstr "en train d'arrêter l'interface utilisateur\n" + +#: gtk_ardour/main.cc:104 +#, c-format +msgid "%d(%d): received signal %d\n" +msgstr "%d(%d) : reçu le signal %d\n" + +#: gtk_ardour/main.cc:190 +msgid "cannot become new process group leader (%1)" +msgstr "" + +#: gtk_ardour/main.cc:217 +msgid "cannot setup signal handling for %1" +msgstr "impossible d'installer le gestionnaire de signaux pour %1" + +#: gtk_ardour/main.cc:228 +msgid "cannot set default signal mask (%1)" +msgstr "impossible de définir le masque de signalisation" + +#: gtk_ardour/main.cc:253 +msgid "" +"Without a UI style file, ardour will look strange.\n" +" Please set ARDOUR_UI_RC to point to a valid UI style file" +msgstr "" +"Sans un fichier de style pour son IHM, ardour aura une apparence bizarre.\n" +"Veuillez faire pointer ARDOUR_UI_RC vers un fichier de style d'IHM valide" + +#: gtk_ardour/main.cc:292 +msgid "" +"Ardour could not connect to JACK.\n" +"There are several possible reasons:\n" +"\n" +"1) JACK is not running.\n" +"2) JACK is running as another user, perhaps root.\n" +"3) There is already another client called \"ardour\".\n" +"\n" +"Please consider the possibilities, and perhaps (re)start JACK." +msgstr "" +"Ardour n'a pas pu se connecter à JACK.\n" +"Il y a plusieurs raisons possibles :\n" +"\n" +"1) JACK n'est pas lancé.\n" +"2) JACK tourne sous un autre utilisateur, peut-être root.\n" +"3) Il y a un autre client appelé \"ardour\".\n" +"\n" +"Veuillez étudier les possibilités, et peut-être (re)lancer JACK." + +#: gtk_ardour/main.cc:305 +msgid "ardour: unplugged" +msgstr "ardour : déconnecté" + +#: gtk_ardour/main.cc:363 +msgid "Ardour/GTK " +msgstr "Ardour/GTK" + +#: gtk_ardour/main.cc:365 +msgid "" +"\n" +" (built using " +msgstr "" +"\n" +" (fonctionnant avec " + +#: gtk_ardour/main.cc:369 +msgid " with libardour " +msgstr " avec libardour " + +#: gtk_ardour/main.cc:374 +msgid " and GCC version " +msgstr "" + +#: gtk_ardour/main.cc:384 +msgid "Copyright (C) 1999-2005 Paul Davis" +msgstr "Copyright (C) 1999-2005 Paul Davis" + +#: gtk_ardour/main.cc:385 +msgid "" +"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel " +"Baker" +msgstr "" +"Certaines parties Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel " +"Baker" + +#: gtk_ardour/main.cc:387 +msgid "Ardour comes with ABSOLUTELY NO WARRANTY" +msgstr "Ardour est distribué sans AUCUNE GARANTIE" + +#: gtk_ardour/main.cc:388 +msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +msgstr "ni même pour la COMMERCIALISATION ou pour UN BUT PARTICULIER." + +#: gtk_ardour/main.cc:389 +msgid "This is free software, and you are welcome to redistribute it " +msgstr "Ceci est un logiciel libre, et vous êtes encouragé à le distribuer " + +#: gtk_ardour/main.cc:390 +msgid "under certain conditions; see the source for copying conditions." +msgstr "" +"sous certaines conditions ; voir le fichier source pour les conditions de " +"distribution." + +#: gtk_ardour/main.cc:399 +msgid "could not create ARDOUR GUI" +msgstr "impossible de créer l'interface utilisateur d'ARDOUR" + +#: gtk_ardour/main.cc:419 +msgid "Could not connect to JACK server as \"%1\"" +msgstr "Impossible de se connecter au serveur JACK en tant que \"%1\"" + +#: gtk_ardour/main.cc:424 +msgid "could not initialize Ardour." +msgstr "impossible d'initialiser Ardour." + +#: gtk_ardour/main.cc:435 +msgid "could not load command line session \"%1\"" +msgstr "impossible de charger la session indiqué en ligne de commande \"%1\"" + +#: gtk_ardour/main.cc:455 +msgid "" +"\n" +"\n" +"A session named \"%1\" already exists.\n" +"To avoid this message, start ardour as \"ardour %1" +msgstr "" +"\n" +"\n" +"Une session nommé \"%1\" existe déjà.\n" +"Pour éviter ce message, lancez ardour comme cela : \"ardour %1" + +#: gtk_ardour/main.cc:466 +msgid "" +"\n" +"\n" +"No session named \"%1\" exists.\n" +"To create it from the command line, start ardour as \"ardour --new %1" +msgstr "" +"\n" +"\n" +"Aucune session nommée \"%1\" n'existe.\n" +"Pour la créer depuis la ligne de commande, lancez ardour comme cela : " +"\"ardour --new %1" + +#: gtk_ardour/marker.cc:354 +#, fuzzy +msgid "MarkerText" +msgstr "Marqueur" + +#: gtk_ardour/marker_time_axis.cc:271 +msgid "Remove Marker" +msgstr "Enlever les marqueurs" + +#: gtk_ardour/marker_time_axis.cc:273 +msgid "Marker" +msgstr "Marqueur" + +#: gtk_ardour/meter_bridge.cc:74 +msgid "ardour: meter bridge" +msgstr "ardour : bandeau de vu-mètre" + +#: gtk_ardour/meter_bridge.cc:75 +msgid "ardour_meter_bridge" +msgstr "ardour_bandeau_vu-mètre" + +#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93 +#, c-format +msgid "# of %u-sample overs" +msgstr "# de %u-échantillons en dépassement" + +#: gtk_ardour/meter_bridge_strip.cc:219 +#, fuzzy +msgid "New name for meter:" +msgstr "Nouveau nom du vu-mètre :" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507 +#: gtk_ardour/region_editor.cc:45 +msgid "mute" +msgstr "muet" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508 +msgid "solo" +msgstr "solo" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506 +msgid "RECORD" +msgstr "ENREGISTRER" + +#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514 +msgid "polarity" +msgstr "polarité" + +#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509 +msgid "comments" +msgstr "commentaires" + +#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810 +msgid "INPUT" +msgstr "ENTRÉE" + +#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831 +msgid "OUTPUT" +msgstr "SORTIE" + +#: gtk_ardour/mixer_strip.cc:173 +msgid "Pan automation mode" +msgstr "Mode d'automatisation de panoramique" + +#: gtk_ardour/mixer_strip.cc:174 +msgid "Gain automation mode" +msgstr "Mode d'automatisation du gain" + +#: gtk_ardour/mixer_strip.cc:176 +msgid "Pan automation type" +msgstr "Type d'automatisation de panoramique" + +#: gtk_ardour/mixer_strip.cc:177 +msgid "Gain automation type" +msgstr "dessiner l'automatisation du gain" + +#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232 +#: gtk_ardour/mixer_strip.cc:979 +msgid "trim" +msgstr "élaguer" + +#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233 +#: gtk_ardour/mixer_strip.cc:983 +msgid "abs" +msgstr "abs" + +#: gtk_ardour/mixer_strip.cc:240 +msgid "gain automation mode" +msgstr "mode d'automatisation du gain" + +#: gtk_ardour/mixer_strip.cc:241 +msgid "pan automation mode" +msgstr "mode d'automatisation de panoramique" + +#: gtk_ardour/mixer_strip.cc:242 +msgid "gain automation state" +msgstr "état de l'automatisation du gain" + +#: gtk_ardour/mixer_strip.cc:243 +msgid "pan automation state" +msgstr "état de l'automatisation de panoramique" + +#: gtk_ardour/mixer_strip.cc:259 +msgid "varispeed" +msgstr "varispeed" + +#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174 +msgid "click to add/edit comments" +msgstr "cliquer pour ajouter/éditer des commentaires" + +#: gtk_ardour/mixer_strip.cc:463 +msgid "unknown strip width \"%1\" in XML GUI information" +msgstr "" +"largeur de tranche inconnue \"%1\" dans les données XML de l'interface " +"utilisateur" + +#: gtk_ardour/mixer_strip.cc:522 +msgid "REC" +msgstr "ENR." + +#: gtk_ardour/mixer_strip.cc:525 +#, fuzzy +msgid "cmt" +msgstr "cmt" + +#: gtk_ardour/mixer_strip.cc:530 +msgid "pol" +msgstr "pol" + +#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620 +#: gtk_ardour/redirect_box.cc:1180 +msgid "Not connected to JACK - no I/O changes are possible" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667 +msgid "could not register new ports required for that connection" +msgstr "impossible de définir les nouveaux ports requis pour cette connexion" + +#: gtk_ardour/mixer_strip.cc:813 +msgid "IN" +msgstr "ENTRÉE" + +#: gtk_ardour/mixer_strip.cc:834 +msgid "OUT" +msgstr "SORTIE" + +#: gtk_ardour/mixer_strip.cc:950 +#, fuzzy +msgid "aplay" +msgstr "aplay" + +#: gtk_ardour/mixer_strip.cc:956 +#, fuzzy +msgid "awrite" +msgstr "awrite" + +#: gtk_ardour/mixer_strip.cc:1134 +msgid ": comment editor" +msgstr ": éditeur de commentaires" + +#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224 +msgid "no group" +msgstr "aucun groupe" + +#: gtk_ardour/mixer_strip.cc:1227 +msgid "~G" +msgstr "~G" + +#: gtk_ardour/mixer_ui.cc:52 +msgid "Strips" +msgstr "Tranches" + +#: gtk_ardour/mixer_ui.cc:56 +msgid "Snapshots" +msgstr "Instantanés" + +#: gtk_ardour/mixer_ui.cc:61 +msgid "***" +msgstr "***" + +#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17 +#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144 +#: gtk_ardour/tempo_dialog.cc:162 +msgid "Bar" +msgstr "Mesure" + +#: gtk_ardour/mixer_ui.cc:121 +msgid "Mix Groups" +msgstr "Groupes de mixage" + +#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373 +msgid "ardour: mixer" +msgstr "ardour : console de mixage" + +#: gtk_ardour/mixer_ui.cc:192 +msgid "ardour_mixer" +msgstr "ardour_console_de_mixage" + +#: gtk_ardour/mixer_ui.cc:342 +msgid "ardour: mixer: " +msgstr "ardour : console de mixage :" + +#: gtk_ardour/mixer_ui.cc:641 +msgid "signal" +msgstr "signal" + +#: gtk_ardour/mixer_ui.cc:672 +msgid "Show All AudioTrack MixerStrips" +msgstr "Montrer toutes les tranches de mixage de piste audio" + +#: gtk_ardour/mixer_ui.cc:673 +msgid "Hide All AudioTrack MixerStrips" +msgstr "Cacher toutes les tranches de mixage de piste audio" + +#: gtk_ardour/mixer_ui.cc:674 +msgid "Show All AudioBus MixerStrips" +msgstr "Montrer toutes les tranches de mixage de bus audio" + +#: gtk_ardour/mixer_ui.cc:675 +msgid "Hide All AudioBus MixerStrips" +msgstr "Cacher toutes les tranches de mixage de bus audio" + +#: gtk_ardour/mixer_ui.cc:687 +msgid "track display list item for renamed strip not found!" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:700 +msgid "Name for new mix group" +msgstr "Nom pour le nouveau groupe de mixage" + +#: gtk_ardour/new_session_dialog.cc:39 +msgid "Session name:" +msgstr "Nom de la session :" + +#: gtk_ardour/new_session_dialog.cc:39 +msgid "Create" +msgstr "Créer" + +#: gtk_ardour/new_session_dialog.cc:40 +#, fuzzy +msgid "use control outs" +msgstr "utiliser les sorties de contrôle" + +#: gtk_ardour/new_session_dialog.cc:41 +msgid "use master outs" +msgstr "utiliser les sorties maître" + +#: gtk_ardour/new_session_dialog.cc:42 +msgid "automatically connect track inputs to physical ports" +msgstr "connecter les entrées de piste aux ports physiques automatiquement" + +#: gtk_ardour/new_session_dialog.cc:43 +msgid "automatically connect track outputs to master outs" +msgstr "connecter les sorties de piste aux sorties maître automatiquement" + +#: gtk_ardour/new_session_dialog.cc:44 +msgid "automatically connect track outputs to physical ports" +msgstr "connecter les sorties de piste aux ports physiques automatiquement" + +#: gtk_ardour/new_session_dialog.cc:45 +msgid "manually connect track outputs" +msgstr "connecter les sorties de piste manuellement" + +#: gtk_ardour/new_session_dialog.cc:50 +msgid "Advanced..." +msgstr "Avancé..." + +#: gtk_ardour/new_session_dialog.cc:52 +msgid "show again" +msgstr "montrer à nouveau" + +#: gtk_ardour/new_session_dialog.cc:55 +msgid "Hardware Inputs: use" +msgstr "Entrées matérielles : utiliser" + +#: gtk_ardour/new_session_dialog.cc:56 +msgid "Hardware Outputs: use" +msgstr "Sorties matérielles : utiliser" + +#: gtk_ardour/new_session_dialog.cc:62 +msgid "new session setup" +msgstr "nouveau paramétrage de session" + +#: gtk_ardour/new_session_dialog.cc:63 +msgid "ardour_new_session" +msgstr "ardour_nouvelle_session" + +#: gtk_ardour/new_session_dialog.cc:72 +msgid "This session will playback and record at %1 Hz" +msgstr "Cette session sera lue et enregistrée à %1 Hz" + +#: gtk_ardour/new_session_dialog.cc:74 +msgid "" +"This rate is set by JACK and cannot be changed.\n" +"If you want to use a different sample rate\n" +"please exit and restart JACK" +msgstr "" +"Cette fréquence est fixée par JACK et ne peut pas être changée.\n" +"Si vous voulez utiliser une autre fréquence d'échantillonage\n" +"veuillez arrêter puis relancer JACK" + +#: gtk_ardour/new_session_dialog.cc:155 +msgid "Session template" +msgstr "Modèle de session" + +#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20 +#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146 +#: gtk_ardour/tempo_dialog.cc:164 +msgid "Location" +msgstr "Emplacement" + +#: gtk_ardour/new_session_dialog.cc:178 +msgid "Configuration" +msgstr "Configuration" + +#: gtk_ardour/new_session_dialog.cc:269 +msgid "blank" +msgstr "vide" + +#: gtk_ardour/new_session_dialog.cc:328 +msgid "No template - create tracks/busses manually" +msgstr "Pas de modèle -- créez les pistes/bus manuellement" + +#: gtk_ardour/new_session_dialog.cc:337 +msgid "No template" +msgstr "Pas de modèle" + +#: gtk_ardour/option_editor.cc:48 +msgid "Internal" +msgstr "Interne" + +#: gtk_ardour/option_editor.cc:49 +msgid "Slave to MTC" +msgstr "Esclave du MTC" + +#: gtk_ardour/option_editor.cc:50 +msgid "Sync with JACK" +msgstr "Synchro. avec JACK" + +#: gtk_ardour/option_editor.cc:51 +msgid "never used but stops crashes" +msgstr "jamais utilisé mais arrête les plantages" + +#: gtk_ardour/option_editor.cc:56 +msgid "Later regions are higher" +msgstr "Les dernières régions sont placées au-dessus" + +#: gtk_ardour/option_editor.cc:57 +msgid "Most recently added/moved/trimmed regions are higher" +msgstr "" +"Les régions ajoutées/déplacées/élaguées en dernier sont placées au-dessus" + +#: gtk_ardour/option_editor.cc:58 +#, fuzzy +msgid "Most recently added regions are higher" +msgstr "" +"Les régions ajoutées/déplacées/élaguées en dernier sont placées au-dessus" + +#: gtk_ardour/option_editor.cc:63 +#, fuzzy +msgid "Span entire region overlap" +msgstr "Mesurer le recouvrement de régions en entier" + +#: gtk_ardour/option_editor.cc:64 +msgid "Short fades at the start of the overlap" +msgstr "Fondus courts en début de recouvrement" + +#: gtk_ardour/option_editor.cc:82 +msgid "Automatically create crossfades" +msgstr "Créer des fondus enchaînés automatiquement" + +#: gtk_ardour/option_editor.cc:83 +msgid "New full-overlap crossfades are unmuted" +msgstr "" +"Les nouveaux fondus enchaînés avec recouvrement complet ne sont pas muets" + +#: gtk_ardour/option_editor.cc:84 +msgid "Region layering mode" +msgstr "Mode de superposition des régions" + +#: gtk_ardour/option_editor.cc:85 +msgid "Crossfade model" +msgstr "Modèle de fondu enchaîné" + +#: gtk_ardour/option_editor.cc:90 +#, fuzzy +msgid "Latched solo" +msgstr "Solo collé" + +#: gtk_ardour/option_editor.cc:91 +msgid "Solo via bus" +msgstr "Solo via le bus" + +#: gtk_ardour/option_editor.cc:96 +msgid "Show waveforms while recording" +msgstr "Montrer les formes d'onde pendant l'enregistrement" + +#: gtk_ardour/option_editor.cc:97 +msgid "Narrow mixer strips" +msgstr "Rétrécir les tranches de mixage" + +#: gtk_ardour/option_editor.cc:98 +msgid "Show measure lines" +msgstr "Montrer les barres de mesures" + +#: gtk_ardour/option_editor.cc:99 +msgid "Follow playhead" +msgstr "Suivre la tête de lecture" + +#: gtk_ardour/option_editor.cc:103 +msgid "Send MTC" +msgstr "Envoyer MTC" + +#: gtk_ardour/option_editor.cc:104 +msgid "Send MMC" +msgstr "Envoyer MMC" + +#: gtk_ardour/option_editor.cc:105 +msgid "JACK time master" +msgstr "JACK horloge maître" + +#: gtk_ardour/option_editor.cc:107 +#, fuzzy +msgid "SMPTE offset is negative" +msgstr "Décalage SMPTE" + +#: gtk_ardour/option_editor.cc:111 +#, fuzzy +msgid "Send MIDI parameter feedback" +msgstr "Envoyer le retour de paramètre MIDI" + +#: gtk_ardour/option_editor.cc:112 +#, fuzzy +msgid "MIDI parameter control" +msgstr "Recevoir le contrôle de paramètre MIDI" + +#: gtk_ardour/option_editor.cc:113 +#, fuzzy +msgid "MMC control" +msgstr "Port MMC" + +#: gtk_ardour/option_editor.cc:131 +#, fuzzy +msgid "Auto-connect new track inputs to hardware" +msgstr "Auto-connexion des nouvelles pistes" + +#: gtk_ardour/option_editor.cc:132 +#, fuzzy +msgid "Auto-connect new track outputs to hardware" +msgstr "Auto-connexion des nouvelles pistes" + +#: gtk_ardour/option_editor.cc:133 +#, fuzzy +msgid "Auto-connect new track outputs to master bus" +msgstr "connecter les sorties de piste aux sorties maître automatiquement" + +#: gtk_ardour/option_editor.cc:134 +#, fuzzy +msgid "Manually connect new track outputs" +msgstr "connecter les sorties de piste manuellement" + +#: gtk_ardour/option_editor.cc:135 +msgid "Use Hardware Monitoring" +msgstr "Utiliser la pré-écoute matérielle" + +#: gtk_ardour/option_editor.cc:136 +msgid "Use Software Monitoring" +msgstr "Utiliser la pré-écoute logicielle" + +#: gtk_ardour/option_editor.cc:137 +msgid "Stop plugins with transport" +msgstr "Arrêter les greffons avec le transport" + +#: gtk_ardour/option_editor.cc:138 +msgid "Run plugins while recording" +msgstr "Activer les greffons durant l'enregistrement" + +#: gtk_ardour/option_editor.cc:139 +#, fuzzy +msgid "Verify remove last capture" +msgstr "Enlever la dernière capture" + +#: gtk_ardour/option_editor.cc:140 +msgid "Stop recording on xrun" +msgstr "Arrêter l'enregistrement en cas de xrun" + +#: gtk_ardour/option_editor.cc:141 +msgid "Stop transport at end of session" +msgstr "Arrêter le transport à la fin de la session" + +#: gtk_ardour/option_editor.cc:142 +msgid "Debug keyboard events" +msgstr "Déboguer les évènements clavier" + +#: gtk_ardour/option_editor.cc:143 +msgid "-12dB gain reduction for ffwd/rew" +msgstr "" + +#: gtk_ardour/option_editor.cc:152 +msgid "ardour: options editor" +msgstr "ardour : éditeur d'options" + +#: gtk_ardour/option_editor.cc:153 +msgid "ardour_option_editor" +msgstr "ardour_éditeur_d_options" + +#: gtk_ardour/option_editor.cc:183 +msgid "Misc" +msgstr "Divers" + +#: gtk_ardour/option_editor.cc:184 +msgid "Sync" +msgstr "Synchro." + +#: gtk_ardour/option_editor.cc:185 +msgid "Paths/Files" +msgstr "Chemins/Fichiers" + +#: gtk_ardour/option_editor.cc:186 +msgid "Display" +msgstr "Affichage" + +#: gtk_ardour/option_editor.cc:187 +msgid "Kbd/Mouse" +msgstr "Clavier/Souris" + +#: gtk_ardour/option_editor.cc:188 +msgid "Click" +msgstr "Clic" + +#: gtk_ardour/option_editor.cc:190 +msgid "Layers & Fades" +msgstr "Couches & fondus" + +#: gtk_ardour/option_editor.cc:195 +msgid "MIDI" +msgstr "MIDI" + +#: gtk_ardour/option_editor.cc:268 +msgid "24 FPS" +msgstr "24 TPS" + +#: gtk_ardour/option_editor.cc:270 +#, fuzzy +msgid "25 FPS" +msgstr "25 TPS" + +#: gtk_ardour/option_editor.cc:272 +#, fuzzy +msgid "30 FPS" +msgstr "30 TPS drop" + +#: gtk_ardour/option_editor.cc:278 +#, fuzzy +msgid "30 FPS drop" +msgstr "30 TPS drop" + +#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379 +#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736 +#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800 +msgid "Medium" +msgstr "Moyen" + +#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738 +#: gtk_ardour/option_editor.cc:804 +msgid "Faster" +msgstr "Plus rapide" + +#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714 +#: gtk_ardour/option_editor.cc:776 +msgid "Short" +msgstr "Court" + +#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716 +#: gtk_ardour/option_editor.cc:780 +msgid "Long" +msgstr "Long" + +#: gtk_ardour/option_editor.cc:396 +msgid "Broadcast WAVE/floating point" +msgstr "Broadcast WAVE/virgule flottante" + +#: gtk_ardour/option_editor.cc:397 +msgid "WAVE/floating point" +msgstr "WAVE/virgule flottante" + +#: gtk_ardour/option_editor.cc:417 +msgid "session RAID path" +msgstr "chemin de session RAID" + +#: gtk_ardour/option_editor.cc:422 +msgid "Native Format" +msgstr "Format natif" + +#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460 +#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409 +msgid "internal" +msgstr "interne" + +#: gtk_ardour/option_editor.cc:537 +msgid "Short crossfade length (msecs)" +msgstr "fondu enchaîné court (ms)" + +#: gtk_ardour/option_editor.cc:710 +msgid "Meter Peak Hold" +msgstr "Maintien du pic de vu-mètre" + +#: gtk_ardour/option_editor.cc:730 +msgid "Meter Falloff" +msgstr "Temps de chute du vu-mètre" + +#: gtk_ardour/option_editor.cc:847 +msgid "Positional Sync" +msgstr "Synchro. positionelle" + +#: gtk_ardour/option_editor.cc:902 +msgid "SMPTE Frames/second" +msgstr "Trames SMPTE/seconde" + +#: gtk_ardour/option_editor.cc:903 +msgid "SMPTE Offset" +msgstr "Décalage SMPTE" + +#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013 +#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211 +#, fuzzy +msgid "online" +msgstr "linéaire" + +#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014 +#: gtk_ardour/option_editor.cc:1208 +#, fuzzy +msgid "offline" +msgstr "linéaire" + +#: gtk_ardour/option_editor.cc:1319 +msgid "Use as click" +msgstr "Utiliser comme clic" + +#: gtk_ardour/option_editor.cc:1344 +msgid "Use as click emphasis" +msgstr "Utiliser comme emphase de clic" + +#: gtk_ardour/option_editor.cc:1478 +msgid "--unknown--" +msgstr "--inconnu--" + +#: gtk_ardour/option_editor.cc:1595 +msgid "Click audio file" +msgstr "Fichier audio de clic" + +#: gtk_ardour/option_editor.cc:1601 +msgid "Click emphasis audiofile" +msgstr "Fichier audio d'emphase de clic" + +#: gtk_ardour/option_editor.cc:1638 +msgid "" +"The auditioner is a dedicated mixer strip used\n" +"for listening to specific regions outside the context\n" +"of the overall mix. It can be connected just like any\n" +"other mixer strip." +msgstr "" +"L'auditioneur est une tranche de mixage dédiée utilisée\n" +"pour écouter des régions spécifiques en dehors du contexte\n" +"du mixage global. Il peut être connecté tout comme n'importe\n" +"quelle autre tranche de mixage." + +#: gtk_ardour/option_editor.cc:1887 +msgid "Edit using" +msgstr "Édition en utilisant" + +#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924 +msgid "+ button" +msgstr "touche +" + +#: gtk_ardour/option_editor.cc:1917 +msgid "Delete using" +msgstr "Effacer en utilisant" + +#: gtk_ardour/option_editor.cc:1947 +msgid "Ignore snap using" +msgstr "Ignorer clac en utilisant" + +#: gtk_ardour/opts.cc:46 +msgid "Usage: " +msgstr "Usage :" + +#: gtk_ardour/opts.cc:47 +msgid " -v, --version Show version information\n" +msgstr "" +" -v, --version Montre les informations de version\n" + +#: gtk_ardour/opts.cc:48 +msgid " -h, --help Print this message\n" +msgstr " -h, --help Affiche ce message\n" + +#: gtk_ardour/opts.cc:49 +msgid "" +" -b, --bindings Print all possible keyboard binding " +"names\n" +msgstr "" +" -b, --bindings Affiche tous raccourcis clavier " +"possibles\n" + +#: gtk_ardour/opts.cc:50 +msgid " -n, --show-splash Show splash screen\n" +msgstr " -n, --show-splash Afficher l'écran de démarrage\n" + +#: gtk_ardour/opts.cc:51 +msgid "" +" -c, --name name Use a specific jack client name, default " +"is ardour\n" +msgstr "" +" -c, --name nom Utiliser un nom de client jack " +"spécifique, la valeur par défaut est ardour\n" + +#: gtk_ardour/opts.cc:52 +msgid "" +" -N, --new session-name Create a new session from the command " +"line\n" +msgstr " -N, --new nom-de-session Nom de la session à charger\n" + +#: gtk_ardour/opts.cc:53 +msgid "" +" -o, --use-hw-optimizations Try to use h/w specific optimizations\n" +msgstr "" + +#: gtk_ardour/opts.cc:55 +msgid " -V, --novst Do not use VST support\n" +msgstr "" + +#: gtk_ardour/opts.cc:57 +msgid " [session-name] Name of session to load\n" +msgstr " [nom-de-session] Nom de la session à charger\n" + +#: gtk_ardour/opts.cc:58 +msgid " -C, --curvetest filename Curve algorithm debugger\n" +msgstr "" +" -C, --curvetest nom-de-fichier Débogueur d'algorithme de courbe\n" + +#: gtk_ardour/pan_automation_time_axis.cc:58 +msgid "You can't graphically edit panning of more than stream" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:78 +#, fuzzy +msgid "add pan automation event" +msgstr "ajouter les évènements d'automatisation à " + +#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441 +msgid "Bypass" +msgstr "Bypass" + +#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222 +#, fuzzy +msgid "link" +msgstr "entrée" + +#: gtk_ardour/panner_ui.cc:103 +msgid "panning link control" +msgstr "" + +#: gtk_ardour/panner_ui.cc:105 +msgid "panning link direction" +msgstr "" + +#: gtk_ardour/panner_ui.cc:232 +msgid "L" +msgstr "" + +#: gtk_ardour/panner_ui.cc:344 +#, c-format +msgid "panner for channel %u" +msgstr "" + +#: gtk_ardour/panner_ui.cc:451 +#, fuzzy +msgid "Reset all" +msgstr "Réinitialiser" + +#: gtk_ardour/playlist_selector.cc:46 +msgid "Playlists grouped by track" +msgstr "" + +#: gtk_ardour/playlist_selector.cc:53 +#, fuzzy +msgid "close" +msgstr "Fermer" + +#: gtk_ardour/playlist_selector.cc:59 +#, fuzzy +msgid "ardour: playlists" +msgstr "ardour : greffons" + +#: gtk_ardour/playlist_selector.cc:104 +#, fuzzy +msgid "ardour: playlist for " +msgstr "ardour : éditeur : " + +#: gtk_ardour/playlist_selector.cc:122 +#, fuzzy +msgid "Other tracks" +msgstr "décaler la piste" + +#: gtk_ardour/playlist_selector.cc:138 +msgid "unassigned" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:41 +msgid "Available LADSPA plugins" +msgstr "Greffons LADSPA disponibles" + +#: gtk_ardour/plugin_selector.cc:42 +msgid "Type" +msgstr "Type" + +#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51 +msgid "# Inputs" +msgstr "# entrées" + +#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52 +msgid "# Outputs" +msgstr "# sorties" + +#: gtk_ardour/plugin_selector.cc:50 +msgid "Available VST plugins" +msgstr "Greffons VST disponibles" + +#: gtk_ardour/plugin_selector.cc:58 +msgid "To be added" +msgstr "À ajouter" + +#: gtk_ardour/plugin_selector.cc:72 +msgid "ardour: plugins" +msgstr "ardour : greffons" + +#: gtk_ardour/plugin_selector.cc:82 +msgid "Add a plugin to the effect list" +msgstr "Ajouter un greffon à la liste d'effets" + +#: gtk_ardour/plugin_selector.cc:84 +msgid "Remove a plugin from the effect list" +msgstr "Retirer un greffon à la liste d'effets" + +#: gtk_ardour/plugin_selector.cc:88 +msgid "Update" +msgstr "Rafraîchir" + +#: gtk_ardour/plugin_selector.cc:89 +msgid "Update available plugins" +msgstr "Rafraîchir les greffons disponibles" + +#: gtk_ardour/plugin_selector.cc:110 +msgid "LADSPA" +msgstr "LADSPA" + +#: gtk_ardour/plugin_selector.cc:113 +msgid "VST" +msgstr "VST" + +#: gtk_ardour/plugin_ui.cc:83 +msgid "" +"unknown type of editor-supplying plugin (note: no VST support in this " +"version of ardour)" +msgstr "" +"type de greffon éditeur inconnu (note : pas de support VST dans cette " +"version d'ardour)" + +#: gtk_ardour/plugin_ui.cc:269 +msgid "Plugin Editor: could not build control element for port %1" +msgstr "" +"Éditeur de greffon : impossible de construire l'élément de contrôle pour le " +"port %1" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "in" +msgstr "entrée" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "ins" +msgstr "entrées" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "out" +msgstr "sortie" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "outs" +msgstr "sorties" + +#: gtk_ardour/plugin_ui.cc:382 +msgid "automation control" +msgstr "contrôle d'automatisation" + +#: gtk_ardour/plugin_ui.cc:869 +msgid "save" +msgstr "enregistrer" + +#: gtk_ardour/plugin_ui.cc:870 +msgid "bypass" +msgstr "bypass" + +#: gtk_ardour/plugin_ui.cc:892 +#, fuzzy +msgid "Plugin preset %1 not found" +msgstr "Pré-réglage de greffon %1 non trouvé" + +#: gtk_ardour/plugin_ui.cc:903 +msgid "Name for plugin settings:" +msgstr "Nom pour les paramètres du greffon :" + +#: gtk_ardour/redirect_automation_line.cc:53 +msgid "redirect automation created for non-plugin" +msgstr "rediriger l'automatisation créée pour le non-greffon" + +#: gtk_ardour/redirect_automation_time_axis.cc:92 +msgid "add automation event to " +msgstr "ajouter les évènements d'automatisation à " + +#: gtk_ardour/redirect_box.cc:213 +msgid "New send" +msgstr "" + +#: gtk_ardour/redirect_box.cc:214 +#, fuzzy +msgid "Show send controls" +msgstr "Contrôle de la vitesse avec molette" + +#: gtk_ardour/redirect_box.cc:360 +msgid "New Plugin ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:361 +#, fuzzy +msgid "New Insert" +msgstr "Nouvelle entrée" + +#: gtk_ardour/redirect_box.cc:362 +msgid "New Send ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:380 +#, fuzzy +msgid "Select all" +msgstr "Tout sélectionner" + +#: gtk_ardour/redirect_box.cc:381 +#, fuzzy +msgid "Deselect all" +msgstr "Tout sélectionner" + +#: gtk_ardour/redirect_box.cc:389 +#, fuzzy +msgid "Inserts" +msgstr "Inverser" + +#: gtk_ardour/redirect_box.cc:390 +#, fuzzy +msgid "Sends" +msgstr "Secondes" + +#: gtk_ardour/redirect_box.cc:393 +#, fuzzy +msgid "Select all ..." +msgstr "Tout sélectionner" + +#: gtk_ardour/redirect_box.cc:406 +#, fuzzy +msgid "Activate All" +msgstr "Activer" + +#: gtk_ardour/redirect_box.cc:407 +#, fuzzy +msgid "Deactivate All" +msgstr "Désactiver" + +#: gtk_ardour/redirect_box.cc:488 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point, there are\n" +"%3 active signal streams.\n" +"\n" +"This makes no sense - you are throwing away\n" +"part of the signal." +msgstr "" + +#: gtk_ardour/redirect_box.cc:500 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point there are\n" +"only %3 active signal streams.\n" +"\n" +"This makes no sense - unless the plugin supports\n" +"side-chain inputs. A future version of Ardour will\n" +"support this type of configuration." +msgstr "" + +#: gtk_ardour/redirect_box.cc:513 +msgid "" +"You attempted to add a plugin (%1).\n" +"\n" +"The I/O configuration doesn't make sense:\n" +"\n" +"The plugin has %2 inputs and %3 outputs.\n" +"The track/bus has %4 inputs and %5 outputs.\n" +"The insertion point, has %6 active signals.\n" +"\n" +"Ardour does not understand what to do in such situations.\n" +msgstr "" + +#: gtk_ardour/redirect_box.cc:616 +msgid "Pre-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:619 +msgid "Post-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:781 +msgid "" +"You cannot reorder this set of redirects\n" +"in that way because the inputs and\n" +"outputs do not work correctly." +msgstr "" + +#: gtk_ardour/redirect_box.cc:903 +#, fuzzy +msgid "ardour: rename redirect" +msgstr "ardour : renommer la région" + +#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043 +msgid "" +"Copying the set of redirects on the clipboard failed,\n" +"probably because the I/O configuration of the plugins\n" +"could not match the configuration of this track." +msgstr "" + +#: gtk_ardour/redirect_box.cc:1064 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this track?\n" +"(this cannot be undone)" +msgstr "" +"Voulez-vous vraiment supprimer la piste \"%1\" ?\n" +"(cela ne pourra pas être annulé)" + +#: gtk_ardour/redirect_box.cc:1067 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this bus?\n" +"(this cannot be undone)" +msgstr "" +"Voulez-vous vraiment supprimer la piste \"%1\" ?\n" +"(cela ne pourra pas être annulé)" + +#: gtk_ardour/redirect_box.cc:1071 +#, fuzzy +msgid "Yes, remove them all" +msgstr "Oui, le supprimer." + +#: gtk_ardour/redirect_box.cc:1114 +#, fuzzy +msgid "ardour: %1" +msgstr "ardour :" + +#: gtk_ardour/redirect_box.cc:1156 +#, fuzzy +msgid "ardour: %1: %2 (by %3)" +msgstr "ardour :" + +#: gtk_ardour/region_editor.cc:43 +msgid "NAME:" +msgstr "NOM :" + +#: gtk_ardour/region_editor.cc:44 +msgid "lock" +msgstr "verrouiller" + +#: gtk_ardour/region_editor.cc:46 +msgid "opaque" +msgstr "opaque" + +#: gtk_ardour/region_editor.cc:49 +msgid "Layer" +msgstr "Couche" + +#: gtk_ardour/region_editor.cc:57 +msgid "ENVELOPE" +msgstr "ENVELOPPE" + +#: gtk_ardour/region_editor.cc:108 +msgid "mute this region" +msgstr "Assourdir cette région" + +#: gtk_ardour/region_editor.cc:109 +msgid "regions underneath this one cannot be heard" +msgstr "les régions en dessous de celle-ci ne peuvent être entendues" + +#: gtk_ardour/region_editor.cc:110 +msgid "prevent any changes to this region" +msgstr "empêche toute modification de cette région" + +#: gtk_ardour/region_editor.cc:111 +msgid "use the gain envelope during playback" +msgstr "utiliser l'enveloppe de gain pendant la lecture" + +#: gtk_ardour/region_editor.cc:112 +msgid "show the gain envelope" +msgstr "montrer l'enveloppe de gain" + +#: gtk_ardour/region_editor.cc:113 +msgid "use fade in curve during playback" +msgstr "utiliser une courbe de fondu d'ouverture durant la lecture" + +#: gtk_ardour/region_editor.cc:114 +msgid "use fade out curve during playback" +msgstr "utiliser une courbe de fondu de fermeture durant la lecture" + +#: gtk_ardour/region_editor.cc:115 +msgid "audition this region" +msgstr "écouter cette région" + +#: gtk_ardour/region_editor.cc:148 +msgid "START:" +msgstr "DÉBUT :" + +#: gtk_ardour/region_editor.cc:150 +msgid "END:" +msgstr "FIN :" + +#: gtk_ardour/region_editor.cc:152 +msgid "LENGTH:" +msgstr "LONGUEUR :" + +#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198 +#: gtk_ardour/region_editor.cc:234 +msgid "active" +msgstr "actif" + +#: gtk_ardour/region_editor.cc:179 +msgid "visible" +msgstr "visible" + +#: gtk_ardour/region_editor.cc:197 +msgid "FADE IN" +msgstr "FONDU D'OUVERTURE" + +#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235 +msgid "msecs" +msgstr "ms" + +#: gtk_ardour/region_editor.cc:233 +msgid "FADE OUT" +msgstr "FONDU DE FERMETURE" + +#: gtk_ardour/region_editor.cc:276 +msgid "ardour: region " +msgstr "ardour : région " + +#: gtk_ardour/region_editor.cc:410 +msgid "fade in edit" +msgstr "édition de fondu d'ouverture" + +#: gtk_ardour/region_editor.cc:422 +msgid "fade out edit" +msgstr "édition de fondu de fermeture" + +#: gtk_ardour/regionview.cc:1169 +#, fuzzy +msgid "add gain control point" +msgstr "Enlever le point de contrôle" + +#: gtk_ardour/route_params_ui.cc:58 +msgid "Tracks/Buses" +msgstr "Pistes/Bus" + +#: gtk_ardour/route_params_ui.cc:59 +msgid "Pre Redirects" +msgstr "Pre redirections" + +#: gtk_ardour/route_params_ui.cc:60 +msgid "Post Redirects" +msgstr "Post redirections" + +#: gtk_ardour/route_params_ui.cc:105 +msgid "Pre-fader Redirects" +msgstr "Redirections pré-fader" + +#: gtk_ardour/route_params_ui.cc:106 +msgid "Post-fader Redirects" +msgstr "Redirections post-fader" + +#: gtk_ardour/route_params_ui.cc:138 +msgid "ardour: track/bus inspector" +msgstr "ardour : inspecteur de piste/bus" + +#: gtk_ardour/route_params_ui.cc:139 +msgid "ardour_route_parameters" +msgstr "ardour_paramètres_de_route" + +#: gtk_ardour/route_params_ui.cc:189 +msgid "route display list item for renamed route not found!" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:448 +msgid "NO TRACK" +msgstr "PAS DE PISTE" + +#: gtk_ardour/route_params_ui.cc:669 +msgid "ardour: track/bus inspector: " +msgstr "ardour : inspecteur de piste/bus" + +#: gtk_ardour/route_params_ui.cc:673 +msgid "No Route Selected" +msgstr "Aucune route sélectionnée" + +#: gtk_ardour/route_params_ui.cc:674 +msgid "ardour: track/bus/inspector: no route selected" +msgstr "ardour : inspecteur de piste/bus : aucune route sélectionnée" + +#: gtk_ardour/route_ui.cc:134 +msgid "mute change" +msgstr "modification de la sourdine" + +#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220 +msgid "solo change" +msgstr "modification du solo" + +#: gtk_ardour/route_ui.cc:284 +#, fuzzy +msgid "rec-enable change" +msgstr "modification de rec-enable" + +#: gtk_ardour/route_ui.cc:423 +#, fuzzy +msgid "Solo-safe" +msgstr "Solo-safe" + +#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474 +msgid "MIDI Bind" +msgstr "Assignement MIDI" + +#: gtk_ardour/route_ui.cc:445 +msgid "Pre Fader" +msgstr "Pré fader" + +#: gtk_ardour/route_ui.cc:452 +msgid "Post Fader" +msgstr "Post fader" + +#: gtk_ardour/route_ui.cc:459 +msgid "Control Outs" +msgstr "Sorties de contrôle" + +#: gtk_ardour/route_ui.cc:466 +msgid "Main Outs" +msgstr "Sorties principales" + +#: gtk_ardour/route_ui.cc:503 +msgid "mix group solo change" +msgstr "" + +#: gtk_ardour/route_ui.cc:537 +msgid "mix group mute change" +msgstr "" + +#: gtk_ardour/route_ui.cc:553 +msgid "mix group rec-enable change" +msgstr "" + +#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258 +msgid "ardour: color selection" +msgstr "ardour : sélection de couleur" + +#: gtk_ardour/route_ui.cc:652 +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"You may also lose the playlist used by this track.\n" +"(cannot be undone)" +msgstr "" +"Voulez-vous vraiment supprimer la piste \"%1\" ?\n" +"Vous perdrez peut-être aussi la liste de lecture utilisée par cette piste" +"(cela ne pourra pas être annulé)" + +#: gtk_ardour/route_ui.cc:654 +msgid "" +"Do you really want to remove bus \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Voulez-vous vraiment supprimer le bus \"%1\" ?\n" +"(cela ne pourra pas être annulé)" + +#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299 +msgid "Yes, remove it." +msgstr "Oui, le supprimer." + +#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358 +msgid "new name: " +msgstr "nouveau nom :" + +#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31 +msgid "Beats per minute" +msgstr "Temps par minute" + +#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35 +#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163 +msgid "Beat" +msgstr "Temps" + +#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158 +msgid "Meter denominator" +msgstr "Dénominateur du vu-mètre" + +#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159 +msgid "Beats per bar" +msgstr "Temps par mesure" + +#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189 +msgid "whole (1)" +msgstr "noire (1)" + +#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191 +msgid "second (2)" +msgstr "croche (2)" + +#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193 +msgid "third (3)" +msgstr "triolet (3)" + +#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195 +#: gtk_ardour/tempo_dialog.cc:203 +msgid "quarter (4)" +msgstr "double croche (4)" + +#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197 +msgid "eighth (8)" +msgstr "huitième (8)" + +#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199 +msgid "sixteenth (16)" +msgstr "seizième (16)" + +#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201 +msgid "thirty-second (32)" +msgstr "trente-deuxième (32)" + +#: gtk_ardour/tempo_dialog.cc:301 +msgid "garbaged note type entry (%1)" +msgstr "entrée type de note endommagée (%1)" + +#: gtk_ardour/tempo_dialog.cc:311 +msgid "incomprehensible note type entry (%1)" +msgstr "entrée type de note incompréhensible (%1)" + +#: gtk_ardour/time_axis_view.cc:95 +msgid "gTortnam" +msgstr "gTortnam" + +#: gtk_ardour/time_axis_view.cc:446 +msgid "Largest" +msgstr "Énorme" + +#: gtk_ardour/time_axis_view.cc:447 +msgid "Large" +msgstr "Grand" + +#: gtk_ardour/time_axis_view.cc:448 +msgid "Larger" +msgstr "Plus grand" + +#: gtk_ardour/time_axis_view.cc:450 +msgid "Smaller" +msgstr "Plus petit" + +#: gtk_ardour/time_axis_view.cc:451 +msgid "Small" +msgstr "Petit" + +#: gtk_ardour/time_axis_view.cc:785 +msgid "unknown track height name \"%1\" in XML GUI information" +msgstr "nom de hauteur de piste inconnu \"%1\" dans les données XML de l'IHM" + +#: gtk_ardour/time_axis_view_item.cc:69 +msgid "TimeAxisViewItemName" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:258 +msgid "new duration %1 frames is out of bounds for %2" +msgstr "la nouvelle durée %1 trames est hors limite pour %2" + +#: gtk_ardour/time_selection.cc:40 +msgid "programming error: request for non-existent audio range (%1)!" +msgstr "programming error: request for non-existent audio range (%1)!" + +#: gtk_ardour/utils.cc:57 +msgid "" +"\"\n" +"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+=" +msgstr "" +"\"\n" +"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+=" + +#: gtk_ardour/utils.cc:66 +msgid "aeiou" +msgstr "aeiou" + +#: gtk_ardour/utils.cc:75 +msgid "AEIOU" +msgstr "AEIOU" + +#: gtk_ardour/utils.cc:84 +msgid "bcdfghjklmnpqrtvwxyz" +msgstr "bcdfghjklmnpqrtvwxyz" + +#: gtk_ardour/utils.cc:93 +msgid "BCDFGHJKLMNPQRTVWXYZ" +msgstr "BCDFGHJKLMNPQRTVWXYZ" + +#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265 +msgid "bad XPM header %1" +msgstr "mauvais entête XPM %1" + +#: gtk_ardour/utils.cc:516 +msgid "missing RGBA style for \"%1\"" +msgstr "" + +#: gtk_ardour/visual_time_axis.cc:297 +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Voulez-vous vraiment supprimer la piste \"%1\" ?\n" +"(cela ne pourra pas être annulé)" + +#: gtk_ardour/visual_time_axis.cc:385 +msgid "A track already exists with that name" +msgstr "Une piste portant le même nom existe déjà" + +#~ msgid "the exact time it was recorded" +#~ msgstr "l'heure exacte de l'enregistrement" + +#~ msgid "existing material that was listened to while recording" +#~ msgstr "son existant qui était écouté pendant l'enregistrement" + +#~ msgid "Seamless Looping" +#~ msgstr "Bouclage sans a-coup" + +#~ msgid "Align recorded material with:" +#~ msgstr "Aligner le son enregistré avec :" + +#~ msgid "Export to CD" +#~ msgstr "Exporter sur CD" + +#~ msgid "programming error: location/marker map does not contain location!" +#~ msgstr "" +#~ "erreur de programmation : la carte d'emplacements/marqueurs ne contient " +#~ "pas d'emplacements !" + +#~ msgid "No toggle button pixmaps found to match toggle-button-[0-9]*.xpm$" +#~ msgstr "" +#~ "Impossible de trouver une image de bouton inverseur qui corresponde à " +#~ "toggle-button-[0-9]*.xpm$" + +#~ msgid "" +#~ "No small push button pixmaps found to match small-round-button-[0-9]*.xpm$" +#~ msgstr "" +#~ "Impossible de trouver une image de petit bouton poussoir qui corresponde " +#~ "à small-round-button-[0-9]*.xpm$" + +#~ msgid "No pixmaps found to match hslider[0-9]*.xpm$" +#~ msgstr "" +#~ "Impossible de trouver une image qui corresponde à hslider[0-9]*.xpm$" + +#~ msgid "No pixmaps found to match vslider[0-9]*.xpm$" +#~ msgstr "" +#~ "Impossible de trouver une image qui corresponde à vslider[0-9]*.xpm$" + +#~ msgid "Recieve MMC" +#~ msgstr "Recevoir MMC" + +#~ msgid "Trace MIDI Input" +#~ msgstr "Suivi des entrées MIDI" + +#~ msgid "Trace MIDI Output" +#~ msgstr "Suivi des sortie MIDI" + +#, fuzzy +#~ msgid "30 FPS non-drop" +#~ msgstr "30 TPS sans-drop" + +#~ msgid "MTC Port" +#~ msgstr "Port MTC" + +#~ msgid "MIDI Param Port" +#~ msgstr "Port de paramètre MIDI" + +#~ msgid "attempt to timestretch a non-audio track!" +#~ msgstr "tentative de déformation temporelle d'une piste non audio !" + +#~ msgid "cannot create timestretch thread - operation not carried out" +#~ msgstr "cannot create timestretch thread - operation not carried out" + +#~ msgid "mouse brush" +#~ msgstr "brosse de souris" + +#~ msgid "move region(s) between tracks" +#~ msgstr "déplacer la/les région(s) entre les pistes" + +#~ msgid "copy region(s) between tracks" +#~ msgstr "copier la/les région(s) entre les pistes" + +#~ msgid "ardour: tempo editor" +#~ msgstr "ardour : éditeur de tempo" + +#~ msgid "ardour_add_track_bus" +#~ msgstr "ardour_ajouter_piste_bus" + +#~ msgid "ok" +#~ msgstr "OK" + +#, fuzzy +#~ msgid "apply" +#~ msgstr "aplay" + +#, fuzzy +#~ msgid "fade" +#~ msgstr "Fades" + +#, fuzzy +#~ msgid "Edit left" +#~ msgstr "Mode d'édition" + +#, fuzzy +#~ msgid "Edit right" +#~ msgstr "Édition en utilisant" + +#, fuzzy +#~ msgid "Edit fade" +#~ msgstr "Mode d'édition" + +#, fuzzy +#~ msgid "Export region" +#~ msgstr "Région" + +#, fuzzy +#~ msgid "Bounce region" +#~ msgstr "Bounce selection" + +#~ msgid "Region" +#~ msgstr "Région" + +#~ msgid "Play selected region" +#~ msgstr "Jouer l'emplacement sélectionné" + +#~ msgid "clear connections" +#~ msgstr "effacer les connexions" + +#, fuzzy +#~ msgid "Crossfades in use" +#~ msgstr "Crossfade" + +#, fuzzy +#~ msgid "outside this computer" +#~ msgstr "Cacher cette piste" + +#, fuzzy +#~ msgid "inside this computer" +#~ msgstr "Cacher cette piste" diff --git a/gtk2_ardour/po/it_IT.po b/gtk2_ardour/po/it_IT.po new file mode 100644 index 0000000000..a497ec2cde --- /dev/null +++ b/gtk2_ardour/po/it_IT.po @@ -0,0 +1,5079 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Paul Davis +# This file is distributed under the same license as the PACKAGE package. +# Filippo Pappalardo , 2003. +# +msgid "" +msgstr "" +"Project-Id-Version: ardour 0.354.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2005-09-19 18:09-0400\n" +"PO-Revision-Date: 2003-05-20 13:03-0500\n" +"Last-Translator: Filippo Pappalardo \n" +"Language-Team: Italian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: gtk_ardour/about.cc:134 +msgid "Marcus Andersson" +msgstr "" + +#: gtk_ardour/about.cc:135 +msgid "Jeremy Hall" +msgstr "" + +#: gtk_ardour/about.cc:136 +msgid "Steve Harris" +msgstr "" + +#: gtk_ardour/about.cc:137 +msgid "Tim Mayberry" +msgstr "" + +#: gtk_ardour/about.cc:138 +msgid "Mark Stewart" +msgstr "" + +#: gtk_ardour/about.cc:139 +msgid "Sam Chessman" +msgstr "" + +#: gtk_ardour/about.cc:140 +msgid "Jack O'Quin" +msgstr "" + +#: gtk_ardour/about.cc:141 +msgid "Matt Krai" +msgstr "" + +#: gtk_ardour/about.cc:142 +msgid "Ben Bell" +msgstr "" + +#: gtk_ardour/about.cc:143 +msgid "Gerard van Dongen" +msgstr "" + +#: gtk_ardour/about.cc:144 +msgid "Thomas Charbonnel" +msgstr "" + +#: gtk_ardour/about.cc:145 +msgid "Nick Mainsbridge" +msgstr "" + +#: gtk_ardour/about.cc:146 +msgid "Colin Law" +msgstr "" + +#: gtk_ardour/about.cc:147 +msgid "Sampo Savolainen" +msgstr "" + +#: gtk_ardour/about.cc:148 +msgid "Joshua Leach" +msgstr "" + +#: gtk_ardour/about.cc:149 +msgid "Rob Holland" +msgstr "" + +#: gtk_ardour/about.cc:150 +msgid "Per Sigmond" +msgstr "" + +#: gtk_ardour/about.cc:151 +msgid "Doug Mclain" +msgstr "" + +#: gtk_ardour/about.cc:156 +msgid "" +"French:\n" +"\tAlain Fréhel " +msgstr "" + +#: gtk_ardour/about.cc:157 +msgid "" +"German:\n" +"\tKarsten Petersen " +msgstr "" + +#: gtk_ardour/about.cc:158 +msgid "" +"Italian:\n" +"\tFilippo Pappalardo " +msgstr "" + +#: gtk_ardour/about.cc:159 +msgid "" +"Portuguese:\n" +"\tRui Nuno Capela " +msgstr "" + +#: gtk_ardour/about.cc:160 +msgid "" +"Brazilian Portuguese:\n" +"\tAlexander da Franca Fernandes \n" +"\tChris Ross " +msgstr "" + +#: gtk_ardour/about.cc:162 +msgid "" +"Spanish:\n" +"\t Alex Krohn " +msgstr "" + +#: gtk_ardour/about.cc:163 +msgid "" +"Russian:\n" +"\t Igor Blinov " +msgstr "" + +#: gtk_ardour/about.cc:181 +msgid "" +"Copyright (C) 1999-2005 Paul Davis\n" +"Ardour comes with ABSOLUTELY NO WARRANTY\n" +"This is free software, and you are welcome to redistribute it\n" +"under certain conditions; see the file COPYING for details.\n" +msgstr "" + +#: gtk_ardour/about.cc:188 +msgid "" +"Ardour: %1\n" +"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)" +msgstr "" + +#: gtk_ardour/about.cc:206 +msgid "" +"Primary author:\n" +"\tPaul Davis\n" +"\n" +"Major developers:\n" +"\tJesse Chappell\n" +"\tTaybin Rutkin\n" +"Contributors:\n" +"\t" +msgstr "" + +#: gtk_ardour/about.cc:243 +msgid "Authors" +msgstr "" + +#: gtk_ardour/about.cc:244 +msgid "Translators" +msgstr "Traduttori" + +#: gtk_ardour/about.cc:361 +msgid "cannot open splash image file \"%1\"" +msgstr "Editor: impossibile l'immagine per lo splash \"%1\" (%2)" + +#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33 +#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81 +#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977 +#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85 +#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777 +#: gtk_ardour/redirect_box.cc:900 +msgid "OK" +msgstr "" + +#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92 +#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046 +#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72 +#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982 +#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733 +#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000 +#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129 +#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785 +#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86 +#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072 +#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33 +#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161 +msgid "Cancel" +msgstr "Cancella" + +#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94 +msgid "Tracks" +msgstr "Tracce" + +#: gtk_ardour/add_route_dialog.cc:43 +msgid "Busses" +msgstr "Bus" + +#: gtk_ardour/add_route_dialog.cc:48 +msgid "ardour: add track/bus" +msgstr "ardour: aggiungi traccia/bus" + +#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81 +msgid "Add" +msgstr "Aggiungi" + +#: gtk_ardour/add_route_dialog.cc:86 +msgid "Name (template)" +msgstr "Nome (modello)" + +#: gtk_ardour/ardour_ui.cc:798 +msgid "" +"pre\n" +"roll" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:799 +msgid "" +"post\n" +"roll" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:807 +msgid "% " +msgstr "" + +#: gtk_ardour/ardour_ui.cc:808 +msgid "spring" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:810 +msgid "" +"punch\n" +"in" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:811 +msgid "" +"punch\n" +"out" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:812 +msgid "" +"auto\n" +"return" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:813 +msgid "" +"auto\n" +"play" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:814 +msgid "" +"auto\n" +"input" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:815 +msgid "click" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:816 +msgid "" +"follow\n" +"PH" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:817 +msgid "AUDITIONING" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:818 +msgid "SOLO" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:870 +msgid "Percentage" +msgstr "Percentuale" + +#: gtk_ardour/ardour_ui.cc:872 +msgid "Semitones" +msgstr "Semitoni" + +#: gtk_ardour/ardour_ui.cc:875 +msgid "Sprung" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:877 +msgid "Wheel" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:902 +msgid "" +"You cannot record-enable\n" +"track %1\n" +"because it has no input connections.\n" +"You would be wasting space recording silence." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1073 +msgid "quit" +msgstr "Esci" + +#: gtk_ardour/ardour_ui.cc:1082 +msgid "" +"Ardour was unable to save your session.\n" +"\n" +"If you still wish to quit, please use the\n" +"\n" +"\"Just quit\" option." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1107 +msgid "Save and %1" +msgstr "Salva ed esci" + +#: gtk_ardour/ardour_ui.cc:1112 +msgid "Just %1" +msgstr "%1 e basta" + +#: gtk_ardour/ardour_ui.cc:1117 +msgid "Don't %1" +msgstr "Non uscire" + +#: gtk_ardour/ardour_ui.cc:1126 +#, fuzzy +msgid "session" +msgstr "Sessione" + +#: gtk_ardour/ardour_ui.cc:1128 +#, fuzzy +msgid "snapshot" +msgstr "Istantanea" + +#: gtk_ardour/ardour_ui.cc:1130 +#, fuzzy +msgid "" +"The %1\n" +"\"%2\"\n" +"has not been saved.\n" +"\n" +"Any changes made this time\n" +"will be lost unless you save it.\n" +"\n" +"What do you want to do?" +msgstr "" +"La sessione \"%1\"\n" +"non è stata salvata.\n" +"\n" +"Qualsiasi cambiamento effettuato adesso\n" +"sarà perduto se non viene salvato.\n" +"\n" +"Cosa vuoi fare?" + +#: gtk_ardour/ardour_ui.cc:1151 +msgid "Prompter" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1152 +msgid "ardour: save session?" +msgstr "ardour: salvare la sessione?" + +#: gtk_ardour/ardour_ui.cc:1219 +#, fuzzy, c-format +msgid "disconnected" +msgstr "Disconnetti" + +#: gtk_ardour/ardour_ui.cc:1226 +#, c-format +msgid "SR: %.1f kHz / %4.1f msecs" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1230 +#, c-format +msgid "SR: %u kHz / %4.1f msecs" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1243 +#, c-format +msgid "DSP Load: %.1f%%" +msgstr "Carico DSP: %.1f%%" + +#: gtk_ardour/ardour_ui.cc:1253 +#, c-format +msgid "Disk r:%5.1f w:%5.1f MB/s" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1267 +#, c-format +msgid "Buffers p:%%% c:%%%" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1294 +msgid "space: 24hrs+" +msgstr "Spazio: 24hrs+" + +#: gtk_ardour/ardour_ui.cc:1324 +#, c-format +msgid "space: %02dh:%02dm:%02ds" +msgstr "Spazio: %02dh:%02dm:%02ds" + +#: gtk_ardour/ardour_ui.cc:1575 +msgid "programming error: impossible control method" +msgstr "errore di programmazione: metodo di controllo impossibile" + +#: gtk_ardour/ardour_ui.cc:1800 +msgid "cancel" +msgstr "cancella" + +#: gtk_ardour/ardour_ui.cc:1801 +msgid "rescan" +msgstr "Aggiorna" + +#: gtk_ardour/ardour_ui.cc:1842 +msgid "open session" +msgstr "apri sessione" + +#: gtk_ardour/ardour_ui.cc:1897 +msgid "Patience is a virtue.\n" +msgstr "La pazienza è una virtù.\n" + +#: gtk_ardour/ardour_ui.cc:1906 +msgid "You cannot add a track without a session already loaded." +msgstr "" +"Non si può aggiungere una traccia senza prima aver caricato una sessione." + +#: gtk_ardour/ardour_ui.cc:1913 +msgid "could not create new audio track" +msgstr "Impossibile creare una nuova traccia audio" + +#: gtk_ardour/ardour_ui.cc:1917 +msgid "could not create new audio bus" +msgstr "Impossibile creare un nuovo bus audio" + +#: gtk_ardour/ardour_ui.cc:1936 +msgid "" +"There are insufficient JACK ports available\n" +"to create a new track or bus.\n" +"You should save Ardour, exit and\n" +"restart JACK with more ports." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2071 +msgid "" +"Please create 1 or more track\n" +"before trying to record.\n" +"Check the Session menu." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2312 +#, fuzzy +msgid "" +"JACK has either been shutdown or it\n" +"disconnected Ardour because Ardour\n" +"was not fast enough. You can save the\n" +"session and/or try to reconnect to JACK ." +msgstr "" +"JACK è stato chiuso oppure ha disconnesso\n" +"Ardour per non essere stato abbastanza veloce.\n" +"E' consigliato salvare la sessione e riavviare\n" +"sia JACK che Ardour." + +#: gtk_ardour/ardour_ui.cc:2328 +msgid "Unable to create all required ports" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2336 +#, fuzzy +msgid "Unable to start the session running" +msgstr "Vai all'inizio della sessione" + +#: gtk_ardour/ardour_ui.cc:2472 +msgid "No Stream" +msgstr "Nessun flusso" + +#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518 +msgid "none" +msgstr "Nessuno" + +#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527 +#: gtk_ardour/automation_time_axis.cc:189 +#: gtk_ardour/automation_time_axis.cc:218 +#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211 +#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947 +#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659 +msgid "off" +msgstr "Off" + +#: gtk_ardour/ardour_ui.cc:2548 +msgid "Name for snapshot" +msgstr "Nome dell' istantanea" + +#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294 +msgid "Name for mix template:" +msgstr "Nome per il modello di mixaggio" + +#: gtk_ardour/ardour_ui.cc:2717 +msgid "-template" +msgstr "-modello" + +#: gtk_ardour/ardour_ui.cc:2760 +msgid "Session %1 already exists at %2" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2832 +msgid "" +"You do not have write access to this session.\n" +"This prevents the session from being loaded." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897 +msgid "Session \"%1 (snapshot %2)\" did not load successfully" +msgstr "La sessione \"%1 (istantanea %2)\" non è stata caricata correttamente" + +#: gtk_ardour/ardour_ui.cc:2966 +msgid "" +"No audio files were ready for cleanup\n" +"\n" +"If this seems suprising, check for any existing\n" +"snapshots. These may still include regions that\n" +"require some unused files to continue to exist." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001 +msgid "files" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003 +msgid "file" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3026 +msgid "ardour: cleanup" +msgstr "ardour: pulisci" + +#: gtk_ardour/ardour_ui.cc:3040 +msgid "" +"Cleanup is a destructive operation.\n" +"ALL undo/redo information will be lost if you cleanup.\n" +"Unused audio files will be moved to a \"dead sounds\" location." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3045 +msgid "Proceed with cleanup" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3061 +#, fuzzy +msgid "CleanupDialog" +msgstr "Pulisci" + +#: gtk_ardour/ardour_ui.cc:3062 +#, fuzzy +msgid "ardour cleanup" +msgstr "ardour: pulisci" + +#: gtk_ardour/ardour_ui.cc:3063 +#, fuzzy +msgid "ardour_cleanup" +msgstr "ardour: pulisci" + +#: gtk_ardour/ardour_ui.cc:3086 +msgid "cleaned files" +msgstr "files ripuliti" + +#: gtk_ardour/ardour_ui.cc:3087 +#, fuzzy +msgid "" +"The following %1 %2 were not in use.\n" +"The next time you flush the wastebasket\n" +"it will release an additional %3 %4bytes\n" +"of disk space" +msgstr "" +"I seguenti %1 files non erano utilizzati.\n" +"La prossima volta che il cestino verr svuotato\n" +"Saranno liberati %2 megabytes di spazio su disco" + +#: gtk_ardour/ardour_ui.cc:3110 +#, fuzzy +msgid "deleted file" +msgstr "files eliminati" + +#: gtk_ardour/ardour_ui.cc:3111 +#, fuzzy +msgid "" +"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space" +msgstr "" +"I seguenti %1 files sono stati eliminati, rilasciati %2 megabytes di spazio " +"disco" + +#: gtk_ardour/ardour_ui.cc:3226 +msgid "Recording was stopped because your system could not keep up." +msgstr "Registazione fermata perche' il sistema non ha retto" + +#: gtk_ardour/ardour_ui.cc:3248 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to write data to disk\n" +"quickly enough to keep up with recording.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3266 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to read data from disk\n" +"quickly enough to keep up with playback.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3291 +msgid "Recover from crash" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3292 +msgid "Ignore crash data" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3293 +msgid "" +"This session appears to have been in\n" +"middle of recording when ardour or\n" +"the computer was shutdown.\n" +"\n" +"Ardour can recover any captured audio for\n" +"you, or it can ignore it. Please decide\n" +"what you would like to do.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3338 +msgid "Could not disconnect from JACK" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3351 +msgid "Could not reconnect to JACK" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:60 +msgid "UI: cannot setup editor" +msgstr "IU: impossibile avviare l'editor" + +#: gtk_ardour/ardour_ui2.cc:65 +msgid "UI: cannot setup mixer" +msgstr "IU: impossibile avviare il mixer" + +#: gtk_ardour/ardour_ui2.cc:70 +msgid "UI: cannot setup meter_bridge" +msgstr "IU: impossibile avviare il meter_bridge" + +#: gtk_ardour/ardour_ui2.cc:98 +msgid "MMC + Local" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:99 +msgid "MMC" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:100 +msgid "Local" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:117 +msgid "MMC ID" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:215 +msgid "Play from playhead" +msgstr "Suona dal cursore" + +#: gtk_ardour/ardour_ui2.cc:216 +msgid "Stop playback" +msgstr "Ferma" + +#: gtk_ardour/ardour_ui2.cc:217 +msgid "Play range/selection" +msgstr "Suona intervallo/selezione" + +#: gtk_ardour/ardour_ui2.cc:218 +msgid "Go to start of session" +msgstr "Vai all'inizio della sessione" + +#: gtk_ardour/ardour_ui2.cc:219 +msgid "Go to end of session" +msgstr "Vai alla fine della sessione" + +#: gtk_ardour/ardour_ui2.cc:220 +msgid "Play loop range" +msgstr "Suona l'intervallo di loop" + +#: gtk_ardour/ardour_ui2.cc:221 +msgid "Return to last playback start when stopped" +msgstr "Torna al punto d'inizio una volta fermato" + +#: gtk_ardour/ardour_ui2.cc:222 +msgid "Start playback after any locate" +msgstr "Comincia a suonare dopo ogni posizione" + +#: gtk_ardour/ardour_ui2.cc:223 +msgid "Be sensible about input monitoring" +msgstr "Monitorizza le entrate" + +#: gtk_ardour/ardour_ui2.cc:224 +msgid "Start recording at auto-punch start" +msgstr "Comincia a registrare al'inizio dell'auto-punch" + +#: gtk_ardour/ardour_ui2.cc:225 +msgid "Stop recording at auto-punch end" +msgstr "Ferma la registrazione alla fine dell'auto-punch" + +#: gtk_ardour/ardour_ui2.cc:226 +msgid "Enable/Disable audio click" +msgstr "Abilita/Disabilita il click audio" + +#: gtk_ardour/ardour_ui2.cc:227 +#, fuzzy +msgid "Enable/Disable follow playhead" +msgstr "Abilita/Disabilita il click audio" + +#: gtk_ardour/ardour_ui2.cc:228 +msgid "Shuttle speed control" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:229 +#, fuzzy, c-format +msgid "Select semitones or %%-age for speed display" +msgstr "Seleziona semitoni o percentuale di velocita' del display" + +#: gtk_ardour/ardour_ui2.cc:230 +msgid "Select sprung or wheel behaviour" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:231 +msgid "Current transport speed" +msgstr "Velocita' del trasporto attuale" + +#: gtk_ardour/ardour_ui2.cc:312 +msgid "Primary clock" +msgstr "Orologio principale" + +#: gtk_ardour/ardour_ui2.cc:313 +msgid "secondary clock" +msgstr "orologio secondario" + +#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751 +#: gtk_ardour/ardour_ui2.cc:770 +msgid "stopped" +msgstr "fermato" + +#: gtk_ardour/ardour_ui2.cc:431 +msgid "ardour: clock" +msgstr "ardour: orologio" + +#: gtk_ardour/ardour_ui2.cc:721 +msgid "st" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:731 +msgid "sprung" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:742 +msgid "wheel" +msgstr "" + +#: gtk_ardour/ardour_ui_dependents.cc:74 +msgid "keyboard_target: error setting binding state: invalid node" +msgstr "" + +#: gtk_ardour/ardour_ui_dialogs.cc:158 +msgid "close session" +msgstr "chiudi la sessione" + +#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895 +msgid "New" +msgstr "Nuovo" + +#: gtk_ardour/ardour_ui_ed.cc:76 +msgid "Open" +msgstr "Apri" + +#: gtk_ardour/ardour_ui_ed.cc:77 +msgid "Recent" +msgstr "Recenti" + +#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +msgid "Close" +msgstr "Chiudi" + +#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488 +msgid "Add Track/Bus" +msgstr "Aggiungi Tracce/Bus" + +#: gtk_ardour/ardour_ui_ed.cc:99 +msgid "Connect" +msgstr "Connetti" + +#: gtk_ardour/ardour_ui_ed.cc:100 +msgid "Image Compositor" +msgstr "Compositore d'Immagini" + +#: gtk_ardour/ardour_ui_ed.cc:114 +msgid "Save" +msgstr "Salva" + +#: gtk_ardour/ardour_ui_ed.cc:118 +msgid "Snapshot" +msgstr "Istantanea" + +#: gtk_ardour/ardour_ui_ed.cc:126 +msgid "Save Template..." +msgstr "Salva Modello..." + +#: gtk_ardour/ardour_ui_ed.cc:133 +msgid "Export session to audiofile..." +msgstr "Esporta la sessione come file audio..." + +#: gtk_ardour/ardour_ui_ed.cc:134 +msgid "Export range to audiofile..." +msgstr "Esporta l'intervallo come file audio..." + +#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312 +#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118 +#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227 +msgid "Export" +msgstr "Esporta" + +#: gtk_ardour/ardour_ui_ed.cc:146 +msgid "Cleanup unused sources" +msgstr "Pulisci sorgenti inutilizzate" + +#: gtk_ardour/ardour_ui_ed.cc:147 +msgid "Flush wastebasket" +msgstr "Svuota il cestino" + +#: gtk_ardour/ardour_ui_ed.cc:149 +msgid "Cleanup" +msgstr "Pulisci" + +#: gtk_ardour/ardour_ui_ed.cc:154 +msgid "Quit" +msgstr "Esci" + +#: gtk_ardour/ardour_ui_ed.cc:156 +msgid "Session" +msgstr "Sessione" + +#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287 +#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499 +#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570 +#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412 +msgid "Edit" +msgstr "Modifica" + +#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572 +#: gtk_ardour/mixer_strip.cc:631 +msgid "Disconnect" +msgstr "Disconnetti" + +#: gtk_ardour/ardour_ui_ed.cc:174 +#, fuzzy +msgid "Reconnect" +msgstr "Connetti" + +#: gtk_ardour/ardour_ui_ed.cc:192 +msgid "Latency" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:195 +msgid "JACK" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:205 +msgid "Editor" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:206 +msgid "Mixer" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:212 +msgid "Options Editor" +msgstr "Editor delle Opzioni" + +#: gtk_ardour/ardour_ui_ed.cc:219 +msgid "Audio Library" +msgstr "Libreria Audio" + +#: gtk_ardour/ardour_ui_ed.cc:225 +#, fuzzy +msgid "Track/Bus Inspector" +msgstr "Tracce/Bus" + +#: gtk_ardour/ardour_ui_ed.cc:232 +msgid "Connections" +msgstr "Connessioni" + +#: gtk_ardour/ardour_ui_ed.cc:240 +msgid "Meter Bridge" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:248 +msgid "Locations" +msgstr "Posizioni" + +#: gtk_ardour/ardour_ui_ed.cc:255 +msgid "Big Clock" +msgstr "Orologio grande" + +#: gtk_ardour/ardour_ui_ed.cc:261 +msgid "About" +msgstr "Circa" + +#: gtk_ardour/ardour_ui_ed.cc:264 +msgid "Windows" +msgstr "Finestre" + +#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203 +msgid "SMPTE" +msgstr "" + +#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202 +#: gtk_ardour/editor_rulers.cc:359 +msgid "Bars:Beats" +msgstr "Battuta:Battiti" + +#: gtk_ardour/audio_clock.cc:1642 +msgid "Minutes:Seconds" +msgstr "Minuti:Secondi" + +#: gtk_ardour/audio_clock.cc:1643 +msgid "Audio Frames" +msgstr "" + +#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356 +#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713 +#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774 +#: gtk_ardour/option_editor.cc:794 +msgid "Off" +msgstr "" + +#: gtk_ardour/audio_clock.cc:1646 +msgid "Mode" +msgstr "Modo" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523 +msgid "m" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524 +msgid "s" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:104 +msgid "r" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:108 +msgid "g" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:109 +msgid "p" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44 +#: gtk_ardour/visual_time_axis.cc:90 +msgid "h" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:111 +msgid "a" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89 +msgid "v" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:185 +msgid "Record" +msgstr "Registra" + +#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191 +msgid "Solo" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236 +#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433 +msgid "Mute" +msgstr "Muto" + +#: gtk_ardour/audio_time_axis.cc:188 +msgid "Edit Group" +msgstr "Modifica Gruppo" + +#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110 +msgid "Display Height" +msgstr "Altezza" + +#: gtk_ardour/audio_time_axis.cc:190 +msgid "Playlist" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752 +msgid "Automation" +msgstr "Automazione" + +#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111 +msgid "Visual options" +msgstr "Opzioni di visualizzazione" + +#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112 +msgid "Hide this track" +msgstr "Nascondi traccia" + +#: gtk_ardour/audio_time_axis.cc:349 +msgid "No group" +msgstr "nessun gruppo" + +#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447 +#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229 +msgid "Height" +msgstr "Altezza" + +#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266 +#: gtk_ardour/marker_time_axis.cc:230 +msgid "Color" +msgstr "Colore" + +#: gtk_ardour/audio_time_axis.cc:720 +msgid "Hide all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:721 +msgid "Show all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:729 +msgid "show all automation" +msgstr "mostra tutte le automazioni" + +#: gtk_ardour/audio_time_axis.cc:732 +msgid "show existing automation" +msgstr "mostra le automazioni esistenti" + +#: gtk_ardour/audio_time_axis.cc:735 +msgid "hide all automation" +msgstr "nascondi tutte le automazioni" + +#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204 +#: gtk_ardour/editor.cc:234 +msgid "gain" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244 +msgid "pan" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388 +msgid "Plugins" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95 +msgid "Show waveforms" +msgstr "Mostra le forme Wave" + +#: gtk_ardour/audio_time_axis.cc:766 +msgid "Traditional" +msgstr "Tradizionale" + +#: gtk_ardour/audio_time_axis.cc:769 +msgid "Rectified" +msgstr "Rettificato" + +#: gtk_ardour/audio_time_axis.cc:772 +msgid "Waveform" +msgstr "Forme wave" + +#: gtk_ardour/audio_time_axis.cc:782 +#, fuzzy +msgid "align with existing material" +msgstr "Materiale esistente" + +#: gtk_ardour/audio_time_axis.cc:787 +#, fuzzy +msgid "align with capture time" +msgstr "Tempo di registrazione" + +#: gtk_ardour/audio_time_axis.cc:793 +#, fuzzy +msgid "Alignment" +msgstr "Allinea" + +#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288 +msgid "Active" +msgstr "Attivo" + +#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386 +#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467 +#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269 +#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233 +#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83 +msgid "Remove" +msgstr "Rimuovi" + +#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880 +#: gtk_ardour/audio_time_axis.cc:911 +#, fuzzy +msgid "Name for playlist" +msgstr "Nome dell' istantanea" + +#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433 +msgid "a track already exists with that name" +msgstr "esiste già una traccia con quel nome" + +#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001 +#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539 +msgid "programming error: " +msgstr "errore di programmazione: " + +#: gtk_ardour/audio_time_axis.cc:1889 +msgid "Current: %1" +msgstr "Corrente %1" + +#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452 +#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226 +#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377 +msgid "Rename" +msgstr "Rinomina" + +#: gtk_ardour/audio_time_axis.cc:1896 +msgid "New Copy" +msgstr "Nuova Copia" + +#: gtk_ardour/audio_time_axis.cc:1898 +msgid "Clear Current" +msgstr "Pulisci Corrente" + +#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472 +#: gtk_ardour/editor.cc:2557 +msgid "Select" +msgstr "Seleziona" + +#: gtk_ardour/automation_line.cc:904 +msgid "automation event move" +msgstr "" + +#: gtk_ardour/automation_line.cc:906 +msgid "automation range drag" +msgstr "" + +#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64 +#, fuzzy +msgid "remove control point" +msgstr "Rimuovi il punto di sincronizzazione" + +#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010 +msgid "clear" +msgstr "pulisci" + +#: gtk_ardour/automation_time_axis.cc:80 +msgid "track height" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:81 +#, fuzzy +msgid "automation state" +msgstr "stato dell'automazione pan" + +#: gtk_ardour/automation_time_axis.cc:82 +#, fuzzy +msgid "clear track" +msgstr "azzera gli intervalli" + +#: gtk_ardour/automation_time_axis.cc:83 +#, fuzzy +msgid "hide track" +msgstr "Nascondi traccia" + +#: gtk_ardour/automation_time_axis.cc:191 +#: gtk_ardour/automation_time_axis.cc:229 +#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213 +#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419 +#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50 +msgid "play" +msgstr "suona" + +#: gtk_ardour/automation_time_axis.cc:193 +#: gtk_ardour/automation_time_axis.cc:240 +#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215 +#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422 +#: gtk_ardour/plugin_ui.cc:663 +msgid "write" +msgstr "scrivi" + +#: gtk_ardour/automation_time_axis.cc:195 +#: gtk_ardour/automation_time_axis.cc:251 +#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217 +#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953 +#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665 +msgid "touch" +msgstr "crea" + +#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274 +#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428 +msgid "???" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:276 +msgid "clear automation" +msgstr "pulisci l'automazione" + +#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453 +#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398 +msgid "Hide" +msgstr "Nascondi" + +#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52 +#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364 +msgid "Clear" +msgstr "Pulisci" + +#: gtk_ardour/automation_time_axis.cc:474 +#, fuzzy +msgid "State" +msgstr "Inizio:" + +#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49 +msgid "Input Connections" +msgstr "Connessioni in entrata" + +#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48 +msgid "Output Connections" +msgstr "Connessioni in uscita" + +#: gtk_ardour/connection_editor.cc:49 +#, fuzzy +msgid "New Input" +msgstr "Nuova entrata" + +#: gtk_ardour/connection_editor.cc:50 +#, fuzzy +msgid "New Output" +msgstr "Nuova uscita" + +#: gtk_ardour/connection_editor.cc:51 +#, fuzzy +msgid "Delete" +msgstr "Elimina" + +#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96 +#, fuzzy +msgid "Add Port" +msgstr "Aggiungi una entrata" + +#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105 +#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786 +#, fuzzy +msgid "Rescan" +msgstr "Aggiorna" + +#: gtk_ardour/connection_editor.cc:101 +msgid "Available Ports" +msgstr "Connessioni disponibili" + +#: gtk_ardour/connection_editor.cc:183 +msgid "ardour: connections" +msgstr "ardour: connessioni" + +#: gtk_ardour/connection_editor.cc:513 +#, c-format +msgid "in %d" +msgstr "" + +#: gtk_ardour/connection_editor.cc:644 +msgid "Name for new connection:" +msgstr "Nome della nuova connessione" + +#: gtk_ardour/crossfade_edit.cc:71 +#, fuzzy +msgid "crossfade editor" +msgstr "modifica lo smorzamento in entrata" + +#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449 +#, fuzzy +msgid "Reset" +msgstr "azzera" + +#: gtk_ardour/crossfade_edit.cc:78 +#, fuzzy +msgid "Fade" +msgstr "Smorzamenti" + +#: gtk_ardour/crossfade_edit.cc:79 +msgid "Out (dry)" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:80 +#, fuzzy +msgid "Out" +msgstr "Uscite" + +#: gtk_ardour/crossfade_edit.cc:81 +msgid "In (dry)" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:82 +msgid "In" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:84 +#, fuzzy +msgid "With Pre-roll" +msgstr "con pre-roll" + +#: gtk_ardour/crossfade_edit.cc:85 +#, fuzzy +msgid "With Post-roll" +msgstr "con post-roll" + +#: gtk_ardour/crossfade_edit.cc:93 +msgid "Fade In" +msgstr "SMORZA Entrata" + +#: gtk_ardour/crossfade_edit.cc:94 +msgid "Fade Out" +msgstr "SMORZA Uscita" + +#: gtk_ardour/crossfade_edit.cc:98 +msgid "ardour: x-fade edit" +msgstr "ardour: modifica lo smorzamento incrociato" + +#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311 +#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189 +msgid "Audition" +msgstr "" + +#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804 +msgid "Regions/name" +msgstr "Regioni/nome" + +#: gtk_ardour/editor.cc:108 +msgid "Chunks" +msgstr "Spezzoni" + +#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079 +msgid "Slide" +msgstr "" + +#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077 +msgid "Splice" +msgstr "" + +#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136 +#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96 +#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977 +msgid "None" +msgstr "Nessuno" + +#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124 +msgid "CD Frames" +msgstr "" + +#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126 +msgid "SMPTE Frames" +msgstr "" + +#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128 +msgid "SMPTE Seconds" +msgstr "" + +#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130 +msgid "SMPTE Minutes" +msgstr "" + +#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132 +msgid "Seconds" +msgstr "Secondi" + +#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134 +msgid "Minutes" +msgstr "Minuti" + +#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106 +msgid "Beats/32" +msgstr "Battiti/32" + +#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104 +msgid "Beats/16" +msgstr "Battiti/16" + +#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102 +msgid "Beats/8" +msgstr "Battiti/8" + +#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100 +msgid "Beats/4" +msgstr "Battiti/4" + +#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098 +msgid "Beats/3" +msgstr "Battiti/3" + +#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108 +msgid "Beats" +msgstr "Battiti" + +#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110 +msgid "Bars" +msgstr "Battute" + +#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112 +msgid "Marks" +msgstr "Marcatori" + +#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114 +#: gtk_ardour/editor.cc:4182 +msgid "Edit Cursor" +msgstr "Cursore di modifica" + +#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116 +msgid "Region starts" +msgstr "Regioni/inizio" + +#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118 +msgid "Region ends" +msgstr "Regioni/fine" + +#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122 +msgid "Region syncs" +msgstr "Regioni/sincronizzazione" + +#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120 +msgid "Region bounds" +msgstr "Regioni/confini" + +#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153 +#: gtk_ardour/time_axis_view.cc:449 +msgid "Normal" +msgstr "Normale" + +#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155 +msgid "Magnetic" +msgstr "Magnetico" + +#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174 +#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237 +msgid "Left" +msgstr "Sinistra" + +#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176 +#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238 +msgid "Right" +msgstr "Destra" + +#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178 +msgid "Center" +msgstr "Centro" + +#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180 +msgid "Playhead" +msgstr "Inizio" + +#: gtk_ardour/editor.cc:201 +msgid "Mins:Secs" +msgstr "Min:Sec" + +#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353 +msgid "Frames" +msgstr "" + +#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373 +msgid "Tempo" +msgstr "" + +#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367 +msgid "Meter" +msgstr "" + +#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379 +msgid "Location Markers" +msgstr "Marcatori di posizione" + +#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385 +msgid "Range Markers" +msgstr "Marcatori di intervallo" + +#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391 +msgid "Loop/Punch Ranges" +msgstr "Intervalli di Loop/Punch" + +#: gtk_ardour/editor.cc:221 +msgid "" +"editor\n" +"mixer" +msgstr "" + +#: gtk_ardour/editor.cc:232 +msgid "range" +msgstr "intervallo" + +#: gtk_ardour/editor.cc:233 +msgid "object" +msgstr "oggetto" + +#: gtk_ardour/editor.cc:235 +msgid "zoom" +msgstr "" + +#: gtk_ardour/editor.cc:236 +msgid "timefx" +msgstr "" + +#: gtk_ardour/editor.cc:237 +msgid "listen" +msgstr "" + +#: gtk_ardour/editor.cc:239 +msgid "mode" +msgstr "modo" + +#: gtk_ardour/editor.cc:240 +msgid "automation" +msgstr "automazione" + +#: gtk_ardour/editor.cc:242 +msgid "Edit Mode" +msgstr "Modalità di modifica" + +#: gtk_ardour/editor.cc:243 +msgid "Snap To" +msgstr "Allinea a" + +#: gtk_ardour/editor.cc:244 +msgid "Snap Mode" +msgstr "Modalita' di Allineamento" + +#: gtk_ardour/editor.cc:245 +msgid "Zoom Focus" +msgstr "" + +#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364 +#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579 +msgid "Nudge" +msgstr "Sposta" + +#: gtk_ardour/editor.cc:511 +msgid "Zoom in" +msgstr "Zoom avanti" + +#: gtk_ardour/editor.cc:512 +msgid "Zoom out" +msgstr "Zoom indietro" + +#: gtk_ardour/editor.cc:517 +msgid "Zoom to session" +msgstr "Zoom alla selezione" + +#: gtk_ardour/editor.cc:536 +msgid "Zoom Span" +msgstr "" + +#: gtk_ardour/editor.cc:566 +msgid "Edit Groups" +msgstr "Modifica Gruppi" + +#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142 +msgid "-all-" +msgstr "-tutto-" + +#: gtk_ardour/editor.cc:718 +msgid "Nudge region/selection forwards" +msgstr "Sposta regione/selezione in avanti" + +#: gtk_ardour/editor.cc:719 +msgid "Nudge region/selection backwards" +msgstr "Sposta regione/selezione indietro" + +#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308 +msgid "ardour: editor" +msgstr "" + +#: gtk_ardour/editor.cc:729 +msgid "ardour_editor" +msgstr "" + +#: gtk_ardour/editor.cc:846 +msgid "VerboseCanvasCursor" +msgstr "" + +#: gtk_ardour/editor.cc:1405 +msgid "FirstActionMessage" +msgstr "" + +#: gtk_ardour/editor.cc:1407 +msgid "Start a new session\n" +msgstr "Inizia una nuova sessione\n" + +#: gtk_ardour/editor.cc:1408 +msgid "via Session menu" +msgstr "tramite il menu Sessione" + +#: gtk_ardour/editor.cc:1703 +msgid "ardour: editor: " +msgstr "" + +#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796 +#: gtk_ardour/editor_markers.cc:797 +msgid "Loop" +msgstr "" + +#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810 +#: gtk_ardour/editor_markers.cc:823 +msgid "Punch" +msgstr "" + +#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688 +msgid "programming error: fade in canvas item has no regionview data pointer!" +msgstr "" + +#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986 +#: gtk_ardour/redirect_box.cc:401 +msgid "Deactivate" +msgstr "Disattiva" + +#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988 +#: gtk_ardour/redirect_box.cc:398 +msgid "Activate" +msgstr "Attiva" + +#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993 +msgid "Linear" +msgstr "Lineare" + +#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994 +#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734 +#: gtk_ardour/option_editor.cc:796 +msgid "Slowest" +msgstr "Piu' Lento" + +#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995 +#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735 +#: gtk_ardour/option_editor.cc:798 +msgid "Slow" +msgstr "Lento" + +#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996 +#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737 +#: gtk_ardour/option_editor.cc:802 +msgid "Fast" +msgstr "Veloce" + +#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997 +#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739 +#: gtk_ardour/option_editor.cc:806 +msgid "Fastest" +msgstr "Più Veloce" + +#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113 +msgid "Freeze" +msgstr "" + +#: gtk_ardour/editor.cc:2109 +msgid "Unfreeze" +msgstr "" + +#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328 +#, fuzzy +msgid "Unmute" +msgstr "muto" + +#: gtk_ardour/editor.cc:2247 +msgid "Convert to short" +msgstr "" + +#: gtk_ardour/editor.cc:2249 +msgid "Convert to full" +msgstr "" + +#: gtk_ardour/editor.cc:2260 +#, fuzzy +msgid "Crossfade" +msgstr "Smorzamento Incrociato" + +#: gtk_ardour/editor.cc:2303 +msgid "Popup region editor" +msgstr "Mostra l'editor di regione" + +#: gtk_ardour/editor.cc:2304 +#, fuzzy +msgid "Raise to top layer" +msgstr "Porta la regione al primo livello" + +#: gtk_ardour/editor.cc:2305 +#, fuzzy +msgid "Lower to bottom layer" +msgstr "Porta la regione all'ultimo livello" + +#: gtk_ardour/editor.cc:2307 +msgid "Define sync point" +msgstr "Definisci il punto di sincronizzazione" + +#: gtk_ardour/editor.cc:2308 +msgid "Remove sync point" +msgstr "Rimuovi il punto di sincronizzazione" + +#: gtk_ardour/editor.cc:2313 +#, fuzzy +msgid "Bounce" +msgstr "Fai il Bounce dell'intervallo" + +#: gtk_ardour/editor.cc:2323 +msgid "Lock" +msgstr "Blocca" + +#: gtk_ardour/editor.cc:2324 +msgid "Unlock" +msgstr "Sblocca" + +#: gtk_ardour/editor.cc:2334 +msgid "Original position" +msgstr "Posizione originale" + +#: gtk_ardour/editor.cc:2340 +msgid "Toggle envelope visibility" +msgstr "" + +#: gtk_ardour/editor.cc:2341 +#, fuzzy +msgid "Toggle envelope active" +msgstr "attivo/passivo" + +#: gtk_ardour/editor.cc:2345 +#, fuzzy +msgid "DeNormalize" +msgstr "Normalizza" + +#: gtk_ardour/editor.cc:2347 +msgid "Normalize" +msgstr "Normalizza" + +#: gtk_ardour/editor.cc:2350 +msgid "Reverse" +msgstr "" + +#: gtk_ardour/editor.cc:2359 +#, fuzzy +msgid "Nudge fwd" +msgstr "Sposta" + +#: gtk_ardour/editor.cc:2360 +#, fuzzy +msgid "Nudge bwd" +msgstr "Sposta" + +#: gtk_ardour/editor.cc:2361 +msgid "Nudge fwd by capture offset" +msgstr "" + +#: gtk_ardour/editor.cc:2362 +msgid "Nudge bwd by capture offset" +msgstr "" + +#: gtk_ardour/editor.cc:2371 +msgid "Start to edit cursor" +msgstr "Inizio al cursore di modifica" + +#: gtk_ardour/editor.cc:2372 +msgid "Edit cursor to end" +msgstr "Cursore di modifica alla fine" + +#: gtk_ardour/editor.cc:2374 +msgid "Trim" +msgstr "" + +#: gtk_ardour/editor.cc:2377 +msgid "Split" +msgstr "Dividi" + +#: gtk_ardour/editor.cc:2380 +msgid "Make mono regions" +msgstr "Crea regioni mono" + +#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428 +msgid "Duplicate" +msgstr "Duplica" + +#: gtk_ardour/editor.cc:2384 +msgid "Fill Track" +msgstr "Riempi Traccia" + +#: gtk_ardour/editor.cc:2388 +msgid "Destroy" +msgstr "Distruggi" + +#: gtk_ardour/editor.cc:2418 +msgid "Play range" +msgstr "Suona l'intervallo" + +#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446 +msgid "Loop range" +msgstr "Intervallo di loop" + +#: gtk_ardour/editor.cc:2421 +msgid "Create chunk from range" +msgstr "Crea uno spezzone dall'intervallo" + +#: gtk_ardour/editor.cc:2423 +msgid "Create Region" +msgstr "Crea una Regione" + +#: gtk_ardour/editor.cc:2424 +msgid "Separate Region" +msgstr "Separa la Regione" + +#: gtk_ardour/editor.cc:2425 +msgid "Crop Region to range" +msgstr "Ridimensiona la Regione alla selezione" + +#: gtk_ardour/editor.cc:2426 +msgid "Bounce range" +msgstr "Fai il Bounce dell'intervallo" + +#: gtk_ardour/editor.cc:2432 +msgid "Fill range w/Region" +msgstr "Riempi intervallo con Regione" + +#: gtk_ardour/editor.cc:2434 +msgid "Range" +msgstr "Intervallo" + +#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538 +msgid "Play from edit cursor" +msgstr "Suona dal cursore di modifica" + +#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539 +msgid "Play from start" +msgstr "Suona dall'inizio" + +#: gtk_ardour/editor.cc:2451 +#, fuzzy +msgid "Play region" +msgstr "Suona la Regione" + +#: gtk_ardour/editor.cc:2453 +msgid "Loop Region" +msgstr "Regione in loop" + +#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540 +#: gtk_ardour/library_ui.cc:972 +msgid "Play" +msgstr "Suona" + +#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548 +msgid "Select All in track" +msgstr "Seleziona tutto nella traccia" + +#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549 +msgid "Select All" +msgstr "Seleziona tutto" + +#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550 +msgid "Invert in track" +msgstr "Inerti nella traccia" + +#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551 +msgid "Invert" +msgstr "Inverti" + +#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553 +msgid "Select loop range" +msgstr "Seleziona l'intervallo di loop" + +#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554 +msgid "Select punch range" +msgstr "Seleziona l'intervallo di punch" + +#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565 +#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369 +msgid "Cut" +msgstr "Taglia" + +#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566 +#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371 +msgid "Copy" +msgstr "Copia" + +#: gtk_ardour/editor.cc:2482 +#, fuzzy +msgid "Paste at edit cursor" +msgstr "Inizio al cursore di modifica" + +#: gtk_ardour/editor.cc:2483 +#, fuzzy +msgid "Paste at mouse" +msgstr "utilizza le uscite master" + +#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923 +msgid "Align" +msgstr "Allinea" + +#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925 +msgid "Align Relative" +msgstr "Allinea Realtivo" + +#: gtk_ardour/editor.cc:2492 +msgid "Insert chunk" +msgstr "Inserisci lo Spezzone" + +#: gtk_ardour/editor.cc:2496 +msgid "New Region from range" +msgstr "Nuova Regione dall'intervallo" + +#: gtk_ardour/editor.cc:2497 +msgid "Separate Range" +msgstr "Separa l'intervallo" + +#: gtk_ardour/editor.cc:2507 +msgid "Insert Region" +msgstr "Inserisci la Regione" + +#: gtk_ardour/editor.cc:2508 +msgid "Insert external sndfile" +msgstr "Inserisci un file audio esterno" + +#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438 +msgid "Import" +msgstr "Importa" + +#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574 +msgid "Nudge entire track fwd" +msgstr "Sposta l'intera traccia in avanti" + +#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575 +msgid "Nudge track after edit cursor fwd" +msgstr "Avanza la traccia dopo il cursore di modifica" + +#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576 +msgid "Nudge entire track bwd" +msgstr "Arretra l'intera traccia" + +#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577 +msgid "Nudge track after edit cursor bwd" +msgstr "Arretra la traccia dopo il cursore di modifica" + +#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920 +#: gtk_ardour/redirect_box.cc:373 +msgid "Paste" +msgstr "Incolla" + +#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645 +#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799 +msgid "add marker" +msgstr "aggiungi marcatore" + +#: gtk_ardour/editor.cc:3084 +msgid "select/move objects" +msgstr "seleziona/muovi gli oggetti" + +#: gtk_ardour/editor.cc:3085 +msgid "select/move ranges" +msgstr "seleziona/muovi range" + +#: gtk_ardour/editor.cc:3086 +msgid "draw gain automation" +msgstr "disegna l'automazione gain" + +#: gtk_ardour/editor.cc:3087 +msgid "select zoom range" +msgstr "seleziona l'intervallo di zoom" + +#: gtk_ardour/editor.cc:3088 +msgid "stretch/shrink regions" +msgstr "allunga/restringi le regioni" + +#: gtk_ardour/editor.cc:3089 +#, fuzzy +msgid "listen to specific regions" +msgstr "Esegui la regione selezionata come loop" + +#: gtk_ardour/editor.cc:3213 +msgid "Start:" +msgstr "Inizio:" + +#: gtk_ardour/editor.cc:3214 +msgid "End:" +msgstr "Fine:" + +#: gtk_ardour/editor.cc:3215 +msgid "Edit:" +msgstr "Modifica:" + +#: gtk_ardour/editor.cc:3429 +msgid "incorrectly formatted URI list, ignored" +msgstr "Lista URI formattata in modo non corretto, ignorata" + +#: gtk_ardour/editor.cc:3611 +#, fuzzy +msgid "set selected trackview" +msgstr "Inserisci selezione" + +#: gtk_ardour/editor.cc:3647 +#, fuzzy +msgid "set selected control point" +msgstr "Rimuovi il punto di sincronizzazione" + +#: gtk_ardour/editor.cc:3719 +#, fuzzy +msgid "set selected regionview" +msgstr "Esegui la regione selezionata come loop" + +#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835 +#, fuzzy +msgid "set selected regions" +msgstr "Esegui la regione selezionata come loop" + +#: gtk_ardour/editor.cc:3891 +msgid "Undo" +msgstr "Annulla" + +#: gtk_ardour/editor.cc:3893 +msgid "Undo (%1)" +msgstr "Annulla (%1)" + +#: gtk_ardour/editor.cc:3903 +msgid "Redo" +msgstr "Ripristina" + +#: gtk_ardour/editor.cc:3905 +msgid "Redo (%1)" +msgstr "Ripristina (%1)" + +#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946 +msgid "... as new track" +msgstr "" + +#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947 +#, fuzzy +msgid "... as new region" +msgstr "Sposta Regione/i" + +#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452 +msgid "Import audio (copy)" +msgstr "Importa audio (copia)" + +#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457 +msgid "Embed audio (link)" +msgstr "Incorpora audio (collegamento)" + +#: gtk_ardour/editor.cc:3953 +msgid "Remove last capture" +msgstr "Rimuovi l'ultima registrazione" + +#: gtk_ardour/editor.cc:3974 +msgid "Duplicate how many times?" +msgstr "Quante volte duplico?" + +#: gtk_ardour/editor.cc:4550 +msgid "" +"Playlist %1 is currently unused.\n" +"If left alone, no audio files used by it will be cleaned.\n" +"If deleted, audio files used by it alone by will cleaned." +msgstr "" + +#: gtk_ardour/editor.cc:4555 +msgid "Delete playlist" +msgstr "" + +#: gtk_ardour/editor.cc:4556 +msgid "Keep playlist" +msgstr "" + +#: gtk_ardour/editor.cc:4557 +#, fuzzy +msgid "Cancel cleanup" +msgstr "Pulisci" + +#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258 +#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290 +msgid "" +"programming error: control point canvas item has no control point object " +"pointer!" +msgstr "" + +#: gtk_ardour/editor_canvas_events.cc:717 +msgid "programming error: line canvas item has no line object pointer!" +msgstr "" + +#: gtk_ardour/editor_canvas_events.cc:744 +#: gtk_ardour/editor_canvas_events.cc:784 +#: gtk_ardour/editor_canvas_events.cc:823 +msgid "programming error: no \"rect\" pointer associated with selection item" +msgstr "" + +#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298 +#: gtk_ardour/mixer_ui.cc:670 +msgid "Show All" +msgstr "Mostra Tutto" + +#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299 +#: gtk_ardour/mixer_ui.cc:671 +msgid "Hide All" +msgstr "Nascondi tutto" + +#: gtk_ardour/editor_edit_groups.cc:98 +msgid "Name for new edit group" +msgstr "Nome per il nuovo gruppo" + +#: gtk_ardour/editor_export_audio.cc:60 +msgid "" +"There is no range to export.\n" +"\n" +"Select a range using the range mouse mode" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707 +msgid "programming error: no ImageFrameView selected" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930 +msgid "programming error: no MarkerView selected" +msgstr "" + +#: gtk_ardour/editor_keys.cc:187 +#, fuzzy +msgid "keyboard selection" +msgstr "Esegui la regione selezionata come loop" + +#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376 +#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526 +#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584 +#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650 +#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700 +#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960 +#: gtk_ardour/editor_mouse.cc:4075 +msgid "programming error: marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681 +msgid "remove marker" +msgstr "rimuovi marcatore" + +#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494 +msgid "Locate to" +msgstr "Posiziona a" + +#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495 +msgid "Play from" +msgstr "Suona da" + +#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496 +msgid "Set from playhead" +msgstr "Imposta dall'inizio" + +#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497 +msgid "Set from range" +msgstr "Imposta dall'intervallo" + +#: gtk_ardour/editor_markers.cc:479 +msgid "Set Loop Range" +msgstr "Imposta l'intervallo di loop" + +#: gtk_ardour/editor_markers.cc:480 +msgid "Set Punch Range" +msgstr "Imposta l'intervallo di Punch" + +#: gtk_ardour/editor_markers.cc:736 +msgid "ardour: rename mark" +msgstr "ardour: rinomina il marcatore" + +#: gtk_ardour/editor_markers.cc:738 +#, fuzzy +msgid "ardour: rename range" +msgstr "ardour: rinomina la regione" + +#: gtk_ardour/editor_markers.cc:792 +#, fuzzy +msgid "set loop range" +msgstr "Seleziona l'intervallo di loop" + +#: gtk_ardour/editor_markers.cc:818 +#, fuzzy +msgid "set punch range" +msgstr "Seleziona l'intervallo di punch" + +#: gtk_ardour/editor_mouse.cc:99 +msgid "Editor::event_frame() used on unhandled event type %1" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1555 +msgid "programming error: start_grab called without drag item" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1760 +msgid "change fade in length" +msgstr "modifica la lunghezza dello smorzamento in entrata" + +#: gtk_ardour/editor_mouse.cc:1778 +msgid "programming error: fade out canvas item has no regionview data pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1852 +msgid "change fade out length" +msgstr "cambia la durata dello smorzamento in uscita" + +#: gtk_ardour/editor_mouse.cc:1871 +msgid "programming error: cursor canvas item has no cursor data pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470 +msgid "" +"programming error: meter marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2163 +#, fuzzy +msgid "move meter mark" +msgstr "rimuovi marcatore" + +#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335 +#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439 +msgid "" +"programming error: tempo marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340 +#: gtk_ardour/editor_tempodisplay.cc:425 +msgid "programming error: marker for tempo is not a tempo marker!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2245 +#, fuzzy +msgid "move tempo mark" +msgstr "rimuovi marcatore" + +#: gtk_ardour/editor_mouse.cc:2388 +msgid "programming error: line canvas item has no line pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2497 +#, fuzzy +msgid "move region(s)" +msgstr "fai il Reverse della regione" + +#: gtk_ardour/editor_mouse.cc:2509 +msgid "Drag region copy" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2579 +#, fuzzy +msgid "copy region(s)" +msgstr "Sposta Regione/i" + +#: gtk_ardour/editor_mouse.cc:2612 +#, fuzzy +msgid "Drag region brush" +msgstr "Sposta Regione/i" + +#: gtk_ardour/editor_mouse.cc:3425 +#, fuzzy +msgid "selection grab" +msgstr "seleziona l'intervallo di zoom" + +#: gtk_ardour/editor_mouse.cc:3571 +#, fuzzy +msgid "range selection" +msgstr "Suona intervallo/selezione" + +#: gtk_ardour/editor_mouse.cc:3587 +#, fuzzy +msgid "trim selection start" +msgstr "Regioni/inizio" + +#: gtk_ardour/editor_mouse.cc:3603 +#, fuzzy +msgid "trim selection end" +msgstr "Importa selezione" + +#: gtk_ardour/editor_mouse.cc:3620 +#, fuzzy +msgid "move selection" +msgstr "Esegui la regione selezionata come loop" + +#: gtk_ardour/editor_mouse.cc:3995 +#, fuzzy +msgid "Start point trim" +msgstr "Inizio al cursore di modifica" + +#: gtk_ardour/editor_mouse.cc:4023 +msgid "End point trim" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:4062 +msgid "trimmed region" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:4203 +#, fuzzy +msgid "new range marker" +msgstr "agggiungi marcatore di intervallo" + +#: gtk_ardour/editor_mouse.cc:4422 +#, fuzzy +msgid "select regions" +msgstr "Esegui la regione selezionata come loop" + +#: gtk_ardour/editor_mouse.cc:4451 +msgid "Name for region:" +msgstr "Nome per la Regione" + +#: gtk_ardour/editor_mouse.cc:4517 +msgid "timestretch" +msgstr "" + +#: gtk_ardour/editor_ops.cc:117 +#, fuzzy +msgid "split" +msgstr "Dividi" + +#: gtk_ardour/editor_ops.cc:153 +#, fuzzy +msgid "remove region" +msgstr "fai il Reverse della regione" + +#: gtk_ardour/editor_ops.cc:172 +msgid "" +" This is destructive, will possibly delete audio files\n" +"It cannot be undone\n" +"Do you really want to destroy %1 ?" +msgstr "" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "these regions" +msgstr "fai il Reverse della regione" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "this region" +msgstr "Metti in muto questa regione" + +#: gtk_ardour/editor_ops.cc:179 +#, fuzzy +msgid "Yes, destroy them." +msgstr "Si, rimuovi." + +#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434 +msgid "Yes, destroy it." +msgstr "Si, rimuovi." + +#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435 +#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300 +msgid "No, do nothing." +msgstr "No, non fare niente." + +#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307 +msgid "extend selection" +msgstr "" + +#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357 +#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427 +msgid "nudge forward" +msgstr "" + +#: gtk_ardour/editor_ops.cc:491 +msgid "build_region_boundary_cache called with snap_type = %1" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1305 +#, fuzzy +msgid "set selection from range" +msgstr "Nuova Regione dall'intervallo" + +#: gtk_ardour/editor_ops.cc:1421 +msgid "clear markers" +msgstr "azzera i marcatori" + +#: gtk_ardour/editor_ops.cc:1433 +msgid "clear ranges" +msgstr "azzera gli intervalli" + +#: gtk_ardour/editor_ops.cc:1452 +msgid "clear locations" +msgstr "azzera le posizioni" + +#: gtk_ardour/editor_ops.cc:1503 +#, fuzzy +msgid "insert dragged region" +msgstr "Inserisci la Regione" + +#: gtk_ardour/editor_ops.cc:1538 +#, fuzzy +msgid "insert region" +msgstr "Inserisci la Regione" + +#: gtk_ardour/editor_ops.cc:1744 +msgid "ardour: rename region" +msgstr "ardour: rinomina la regione" + +#: gtk_ardour/editor_ops.cc:1891 +msgid "You can't import an audiofile until you have a session loaded." +msgstr "" +"Non si può importare un file audio senza prima aver caricato una sessione" + +#: gtk_ardour/editor_ops.cc:1901 +#, fuzzy +msgid "Import selected as tracks" +msgstr "Importa selezione" + +#: gtk_ardour/editor_ops.cc:1904 +#, fuzzy +msgid "Import selected to region list" +msgstr "Esegui la regione selezionata come loop" + +#: gtk_ardour/editor_ops.cc:1933 +msgid "ardour: audio import in progress" +msgstr "ardour: importazione audio in corso" + +#: gtk_ardour/editor_ops.cc:1937 +msgid "Cancel Import" +msgstr "Annullare l'importazione" + +#: gtk_ardour/editor_ops.cc:1944 +msgid "ardour: importing %1" +msgstr "ardour: importazione di %1" + +#: gtk_ardour/editor_ops.cc:1990 +msgid "%1 it anyway" +msgstr "%1 comunque" + +#: gtk_ardour/editor_ops.cc:1996 +#, fuzzy +msgid "Don't %1 it" +msgstr "Non uscire" + +#: gtk_ardour/editor_ops.cc:1997 +msgid "%1 all without questions" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1998 +#, fuzzy +msgid "Cancel entire import" +msgstr "Annullare l'importazione" + +#: gtk_ardour/editor_ops.cc:2004 +#, fuzzy +msgid "" +"%1\n" +"This audiofile's sample rate doesn't match the session sample rate!" +msgstr "Il sample rate del file audio non corrisponde a quello della sessione!" + +#: gtk_ardour/editor_ops.cc:2032 +msgid "You can't embed an audiofile until you have a session loaded." +msgstr "" +"Non si può collegare un file audio senza prima aver caricato una sessione" + +#: gtk_ardour/editor_ops.cc:2039 +msgid "Add to External Region list" +msgstr "Aggiungi alla lista di Regioni Esterne" + +#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210 +#: gtk_ardour/editor_ops.cc:2286 +msgid "Editor: cannot open file \"%1\" (%2)" +msgstr "Editor: impossibile aprire il file \"%1\" (%2)" + +#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312 +msgid "could not open %1" +msgstr "impossibile aprire %1" + +#: gtk_ardour/editor_ops.cc:2171 +#, fuzzy +msgid "Insert selected as new tracks" +msgstr "Inserisci selezione" + +#: gtk_ardour/editor_ops.cc:2186 +msgid "Insert selected" +msgstr "Inserisci selezione" + +#: gtk_ardour/editor_ops.cc:2327 +#, fuzzy +msgid "insert sndfile" +msgstr "Inserisci un file audio esterno" + +#: gtk_ardour/editor_ops.cc:2464 +#, fuzzy +msgid "separate" +msgstr "Separa l'intervallo" + +#: gtk_ardour/editor_ops.cc:2528 +#, fuzzy +msgid "trim to selection" +msgstr "ardour: selezione del colore" + +#: gtk_ardour/editor_ops.cc:2568 +msgid "region fill" +msgstr "" + +#: gtk_ardour/editor_ops.cc:2626 +#, fuzzy +msgid "fill selection" +msgstr "Suona intervallo/selezione" + +#: gtk_ardour/editor_ops.cc:2650 +msgid "Place the edit cursor at the desired sync point" +msgstr "" +"Posiziona il cursore di modifica al punto di sincronizzazione desiderato" + +#: gtk_ardour/editor_ops.cc:2656 +#, fuzzy +msgid "set sync from edit cursor" +msgstr "Suona dal cursore di modifica" + +#: gtk_ardour/editor_ops.cc:2668 +#, fuzzy +msgid "remove sync" +msgstr "Rimuovi il punto di sincronizzazione" + +#: gtk_ardour/editor_ops.cc:2682 +#, fuzzy +msgid "naturalize" +msgstr "Normalizza" + +#: gtk_ardour/editor_ops.cc:2746 +#, fuzzy +msgid "align selection (relative)" +msgstr "Allinea Realtivo" + +#: gtk_ardour/editor_ops.cc:2774 +#, fuzzy +msgid "align selection" +msgstr "ardour: selezione del colore" + +#: gtk_ardour/editor_ops.cc:2786 +#, fuzzy +msgid "align region" +msgstr "Sposta Regione/i" + +#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858 +#, fuzzy +msgid "trim to edit" +msgstr "Inizio al cursore di modifica" + +#: gtk_ardour/editor_ops.cc:2909 +#, fuzzy +msgid "ardour: freeze" +msgstr "ardour: rinomina la regione" + +#: gtk_ardour/editor_ops.cc:2914 +#, fuzzy +msgid "Cancel Freeze" +msgstr "Cancella" + +#: gtk_ardour/editor_ops.cc:2951 +#, fuzzy +msgid "bounce range" +msgstr "Fai il Bounce dell'intervallo" + +#: gtk_ardour/editor_ops.cc:3004 +msgid "cut" +msgstr "taglia" + +#: gtk_ardour/editor_ops.cc:3007 +msgid "copy" +msgstr "copia" + +#: gtk_ardour/editor_ops.cc:3020 +msgid " objects" +msgstr "oggetti" + +#: gtk_ardour/editor_ops.cc:3046 +msgid " range" +msgstr " intervallo" + +#: gtk_ardour/editor_ops.cc:3201 +#, fuzzy +msgid "paste" +msgstr "Incolla" + +#: gtk_ardour/editor_ops.cc:3236 +#, fuzzy +msgid "paste chunk" +msgstr "Crea uno Spezzone" + +#: gtk_ardour/editor_ops.cc:3276 +#, fuzzy +msgid "duplicate region" +msgstr "Esegui la regione selezionata come loop" + +#: gtk_ardour/editor_ops.cc:3309 +#, fuzzy +msgid "duplicate selection" +msgstr "ardour: selezione del colore" + +#: gtk_ardour/editor_ops.cc:3349 +#, fuzzy +msgid "clear playlist" +msgstr "azzera le posizioni" + +#: gtk_ardour/editor_ops.cc:3378 +#, fuzzy +msgid "nudge track" +msgstr "Nascondi traccia" + +#: gtk_ardour/editor_ops.cc:3431 +msgid "" +"Do you really want to destroy the last capture?\n" +"(This is destructive and cannot be undone)" +msgstr "" +"Si vuole realmente rimuovere l'ultima registrazione?\n" +"(questa azione non potrà essere annullata)" + +#: gtk_ardour/editor_ops.cc:3463 +#, fuzzy +msgid "normalize" +msgstr "Normalizza" + +#: gtk_ardour/editor_ops.cc:3510 +msgid "reverse regions" +msgstr "fai il Reverse della regione" + +#: gtk_ardour/editor_region_list.cc:223 +#, fuzzy +msgid "hidden" +msgstr "Nascosto" + +#: gtk_ardour/editor_region_list.cc:408 +msgid "Show all" +msgstr "Mostra tutto" + +#: gtk_ardour/editor_region_list.cc:417 +msgid "Ascending" +msgstr "Ascendente" + +#: gtk_ardour/editor_region_list.cc:419 +msgid "Descending" +msgstr "Discendente" + +#: gtk_ardour/editor_region_list.cc:423 +msgid "By Region Name" +msgstr "Per Nome di Regione" + +#: gtk_ardour/editor_region_list.cc:425 +msgid "By Region Length" +msgstr "Per Lunghezza di Regione" + +#: gtk_ardour/editor_region_list.cc:427 +msgid "By Region Position" +msgstr "Per Posizione della Regione" + +#: gtk_ardour/editor_region_list.cc:429 +msgid "By Region Timestamp" +msgstr "Per Data di Regione" + +#: gtk_ardour/editor_region_list.cc:431 +msgid "By Region Start in File" +msgstr "Per Inizio di Regione nel file" + +#: gtk_ardour/editor_region_list.cc:433 +msgid "By Region End in File" +msgstr "Per Fine di Regione nel file" + +#: gtk_ardour/editor_region_list.cc:435 +msgid "By Source File Name" +msgstr "Per Nome di sorgente del file" + +#: gtk_ardour/editor_region_list.cc:437 +msgid "By Source File Length" +msgstr "Per Lunghezza di sorgente del file" + +#: gtk_ardour/editor_region_list.cc:439 +msgid "By Source File Creation Date" +msgstr "Per Data di creazione di sorgente del file" + +#: gtk_ardour/editor_region_list.cc:441 +msgid "By Source Filesystem" +msgstr "Per Filesystem di sorgente" + +#: gtk_ardour/editor_region_list.cc:444 +msgid "Sorting" +msgstr "Ordinamento" + +#: gtk_ardour/editor_region_list.cc:808 +msgid "Regions/length" +msgstr "Regioni/lunghezza" + +#: gtk_ardour/editor_region_list.cc:812 +msgid "Regions/position" +msgstr "Regioni/posizione" + +#: gtk_ardour/editor_region_list.cc:816 +msgid "Regions/creation" +msgstr "Regioni/creazione" + +#: gtk_ardour/editor_region_list.cc:820 +msgid "Regions/start" +msgstr "Regioni/inizio" + +#: gtk_ardour/editor_region_list.cc:824 +msgid "Regions/end" +msgstr "Regioni/fine" + +#: gtk_ardour/editor_region_list.cc:828 +msgid "Regions/file name" +msgstr "Regioni/nome file" + +#: gtk_ardour/editor_region_list.cc:832 +msgid "Regions/file size" +msgstr "Regioni/dimensioni file" + +#: gtk_ardour/editor_region_list.cc:836 +msgid "Regions/file date" +msgstr "Regioni/data file" + +#: gtk_ardour/editor_region_list.cc:840 +msgid "Regions/file system" +msgstr "Regioni/file system" + +#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73 +#: gtk_ardour/editor_route_list.cc:231 +msgid "editor" +msgstr "" + +#: gtk_ardour/editor_route_list.cc:300 +msgid "Show All AbstractTracks" +msgstr "Mostra tutte le Tracce" + +#: gtk_ardour/editor_route_list.cc:301 +msgid "Hide All AbstractTracks" +msgstr "Nascondi tutte le Tracce" + +#: gtk_ardour/editor_route_list.cc:302 +msgid "Show All AudioBus" +msgstr "Mostra tutti i Bus Audio" + +#: gtk_ardour/editor_route_list.cc:303 +msgid "Hide All AudioBus" +msgstr "Nascondi tutti i Bus Audio" + +#: gtk_ardour/editor_rulers.cc:311 +msgid "New location marker" +msgstr "Marcatore di nuova posizione" + +#: gtk_ardour/editor_rulers.cc:312 +msgid "Clear all locations" +msgstr "Pulisci tutte le posizioni" + +#: gtk_ardour/editor_rulers.cc:317 +msgid "Clear all ranges" +msgstr "Pulisci tutti gli intervalli" + +#: gtk_ardour/editor_rulers.cc:326 +msgid "New Tempo" +msgstr "Nuovo tempo" + +#: gtk_ardour/editor_rulers.cc:327 +msgid "Clear tempo" +msgstr "Pulisci tempo" + +#: gtk_ardour/editor_rulers.cc:332 +msgid "New Meter" +msgstr "Nuovo Meter" + +#: gtk_ardour/editor_rulers.cc:333 +msgid "Clear meter" +msgstr "Pulisci Meter" + +#: gtk_ardour/editor_rulers.cc:341 +msgid "Min:Secs" +msgstr "Min:Sec" + +#: gtk_ardour/editor_selection_list.cc:117 +msgid "name for chunk:" +msgstr "Nome dello Spezzone" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Create chunk" +msgstr "Crea uno Spezzone" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Forget it" +msgstr "Annulla" + +#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295 +msgid "add" +msgstr "Aggiungi" + +#: gtk_ardour/editor_tempodisplay.cc:276 +#, fuzzy +msgid "add tempo mark" +msgstr "agggiungi marcatore di intervallo" + +#: gtk_ardour/editor_tempodisplay.cc:318 +#, fuzzy +msgid "add meter mark" +msgstr "agggiungi marcatore di intervallo" + +#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383 +msgid "done" +msgstr "fatto" + +#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404 +msgid "replace tempo mark" +msgstr "" + +#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475 +msgid "programming error: marker for meter is not a meter marker!" +msgstr "" + +#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487 +#, fuzzy +msgid "remove tempo mark" +msgstr "rimuovi marcatore" + +#: gtk_ardour/editor_timefx.cc:50 +msgid "Quick but Ugly" +msgstr "Rapido ma inaccurato" + +#: gtk_ardour/editor_timefx.cc:51 +msgid "Skip Anti-aliasing" +msgstr "Salta l'Anti-aliasing" + +#: gtk_ardour/editor_timefx.cc:53 +msgid "Stretch/Shrink it" +msgstr "Allunga/Restringi" + +#: gtk_ardour/editor_timefx.cc:57 +msgid "ardour: timestretch" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:58 +msgid "TimeStretchDialog" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83 +#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85 +msgid "TimeStretchButton" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:86 +msgid "TimeStretchProgress" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:151 +msgid "timestretch cannot be started - thread creation error" +msgstr "" + +#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410 +#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189 +msgid "22.05kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413 +#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949 +#: gtk_ardour/export_dialog.cc:1191 +msgid "44.1kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416 +#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193 +msgid "48kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419 +#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195 +msgid "88.2kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422 +#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197 +msgid "96kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425 +#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199 +msgid "192kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:73 +msgid "best" +msgstr "migliore" + +#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964 +msgid "fastest" +msgstr "più veloce" + +#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966 +msgid "linear" +msgstr "lineare" + +#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968 +msgid "better" +msgstr "meglio" + +#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970 +msgid "intermediate" +msgstr "medio" + +#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979 +msgid "Rectangular" +msgstr "Rettangolare" + +#: gtk_ardour/export_dialog.cc:84 +msgid "Shaped Noise" +msgstr "" + +#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981 +msgid "Triangular" +msgstr "Triangolare" + +#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336 +msgid "stereo" +msgstr "" + +#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497 +#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219 +#: gtk_ardour/utils.cc:334 +msgid "mono" +msgstr "" + +#: gtk_ardour/export_dialog.cc:97 +msgid "CUE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:98 +msgid "TOC" +msgstr "" + +#: gtk_ardour/export_dialog.cc:106 +msgid "FORMAT" +msgstr "FORMATO" + +#: gtk_ardour/export_dialog.cc:107 +msgid "SAMPLE RATE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:108 +msgid "CONVERSION QUALITY" +msgstr "QUALITÀ DI CONVERSIONE" + +#: gtk_ardour/export_dialog.cc:109 +msgid "DITHER TYPE" +msgstr "TIPO DI DITHER" + +#: gtk_ardour/export_dialog.cc:110 +#, fuzzy +msgid "CD MARKER FILE TYPE" +msgstr "TIPO DI FILE" + +#: gtk_ardour/export_dialog.cc:111 +msgid "CHANNELS" +msgstr "CANALI" + +#: gtk_ardour/export_dialog.cc:112 +msgid "FILE TYPE" +msgstr "TIPO DI FILE" + +#: gtk_ardour/export_dialog.cc:113 +msgid "SAMPLE FORMAT" +msgstr "FORMATO DEL CAMPIONE" + +#: gtk_ardour/export_dialog.cc:114 +msgid "SAMPLE ENDIANNESS" +msgstr "ENDIANNES DEL CAMPIONE" + +#: gtk_ardour/export_dialog.cc:115 +#, fuzzy +msgid "EXPORT CD MARKER FILE ONLY" +msgstr "TIPO DI FILE" + +#: gtk_ardour/export_dialog.cc:116 +msgid "EXPORT TO FILE" +msgstr "ESPORTA SU FILE" + +#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118 +#: gtk_ardour/option_editor.cc:119 +msgid "Browse" +msgstr "Naviga" + +#: gtk_ardour/export_dialog.cc:119 +msgid "Specific tracks ..." +msgstr "" + +#: gtk_ardour/export_dialog.cc:131 +msgid "ardour: export" +msgstr "ardour: esportazione" + +#: gtk_ardour/export_dialog.cc:132 +#, fuzzy +msgid "ardour_export" +msgstr "ardour: esportazione" + +#: gtk_ardour/export_dialog.cc:156 +#, fuzzy +msgid "Output" +msgstr "Uscite" + +#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626 +msgid "Track" +msgstr "Traccia" + +#: gtk_ardour/export_dialog.cc:287 +msgid "slereg" +msgstr "" + +#: gtk_ardour/export_dialog.cc:658 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD toc file" +msgstr "" +"Editor: impossibile aprire \"%1\" come file da esportare a marcatori di " +"tracce per CD" + +#: gtk_ardour/export_dialog.cc:780 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD cue file" +msgstr "" +"Editor: impossibile aprire \"%1\" come file da esportare a marcatori di " +"tracce per CD" + +#: gtk_ardour/export_dialog.cc:799 +msgid "WAV" +msgstr "" + +#: gtk_ardour/export_dialog.cc:1051 +msgid "Stop Export" +msgstr "Ferma esportazione" + +#: gtk_ardour/gain_automation_time_axis.cc:60 +#, fuzzy +msgid "add gain automation event" +msgstr "aggiungi evento di automazione a " + +#: gtk_ardour/gain_meter.cc:68 +msgid "Cannot create slider pixmaps" +msgstr "" + +#: gtk_ardour/gain_meter.cc:83 +msgid "dbFS" +msgstr "" + +#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134 +#: gtk_ardour/gain_meter.cc:728 +msgid "pre" +msgstr "" + +#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724 +#, fuzzy +msgid "input" +msgstr "entrata %1" + +#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732 +#, fuzzy +msgid "post" +msgstr "entrata" + +#: gtk_ardour/gain_meter.cc:146 +msgid "tupni" +msgstr "" + +#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470 +#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537 +msgid "-inf" +msgstr "" + +#: gtk_ardour/imageframe_socket_handler.cc:127 +msgid "Image Compositor Socket has been shutdown/closed" +msgstr "" + +#: gtk_ardour/imageframe_time_axis.cc:295 +#, fuzzy +msgid "0.5 seconds" +msgstr "Secondi" + +#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259 +#, fuzzy +msgid "1 seconds" +msgstr "Secondi" + +#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260 +#, fuzzy +msgid "1.5 seconds" +msgstr "Secondi" + +#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261 +#, fuzzy +msgid "2 seconds" +msgstr "Secondi" + +#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262 +#, fuzzy +msgid "2.5 seconds" +msgstr "Secondi" + +#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263 +#, fuzzy +msgid "3 seconds" +msgstr "Secondi" + +#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268 +#, fuzzy +msgid "Duration (sec)" +msgstr "Sposta Regione/i" + +#: gtk_ardour/imageframe_time_axis.cc:310 +#, fuzzy +msgid "Remove Frame" +msgstr "Rimuovi Campo" + +#: gtk_ardour/imageframe_time_axis.cc:313 +msgid "Image Frame" +msgstr "" + +#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274 +#, fuzzy +msgid "Rename Track" +msgstr "Rinomina" + +#: gtk_ardour/io_selector.cc:64 +msgid "%1 input" +msgstr "entrata %1" + +#: gtk_ardour/io_selector.cc:66 +msgid "%1 output" +msgstr "uscita %1" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103 +msgid "Inputs" +msgstr "Entrate" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104 +msgid "Outputs" +msgstr "Uscite" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Input" +msgstr "aggiungi una entrata" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Output" +msgstr "aggiungi una uscita" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Input" +msgstr "Rimuovi il punto di sincronizzazione" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Output" +msgstr "# Uscite" + +#: gtk_ardour/io_selector.cc:144 +#, fuzzy +msgid "Disconnect All" +msgstr "Disconnetti" + +#: gtk_ardour/io_selector.cc:158 +msgid "Available connections" +msgstr "Connessioni disponibili" + +#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636 +#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724 +msgid "port" +msgstr "entrata" + +#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587 +msgid "There are no more JACK ports available." +msgstr "" + +#: gtk_ardour/io_selector.cc:790 +msgid "ardour: " +msgstr "" + +#: gtk_ardour/keyboard.cc:419 +msgid "KeyboardTarget: keyname \"%1\" is unknown." +msgstr "KeyboardTarget: il keyname \"%1\" è sconosciuto" + +#: gtk_ardour/keyboard.cc:645 +msgid "" +"Your system is completely broken - NumLock uses \"%1\"as its modifier. This " +"is madness - see the man page for xmodmap to find out how to fix this." +msgstr "" + +#: gtk_ardour/keyboard.cc:653 +msgid "" +"Your system generates \"%1\" when the NumLock key is pressed. This can cause " +"problems when editing so Ardour will use %2 to mean Meta rather than %1" +msgstr "" + +#: gtk_ardour/keyboard.cc:714 +msgid "You have %1 keys bound to \"mod1\"" +msgstr "" + +#: gtk_ardour/keyboard.cc:729 +msgid "You have %1 keys bound to \"mod2\"" +msgstr "" + +#: gtk_ardour/keyboard.cc:744 +msgid "You have %1 keys bound to \"mod3\"" +msgstr "" + +#: gtk_ardour/keyboard.cc:759 +msgid "You have %1 keys bound to \"mod4\"" +msgstr "" + +#: gtk_ardour/keyboard.cc:774 +msgid "You have %1 keys bound to \"mod5\"" +msgstr "" + +#: gtk_ardour/keyboard_target.cc:72 +msgid "KeyboardTarget: empty string passed to add_binding." +msgstr "" + +#: gtk_ardour/keyboard_target.cc:78 +msgid "KeyboardTarget: no translation found for \"%1\"" +msgstr "KeyboardTarget: nessuna traduzione trovata per \"%1\"" + +#: gtk_ardour/keyboard_target.cc:83 +msgid "KeyboardTarget: unknown action \"%1\"" +msgstr "KeyboardTarget: \"1\" azione sconosciuta" + +#: gtk_ardour/keyboard_target.cc:248 +msgid "misformed binding node - ignored" +msgstr "" + +#: gtk_ardour/library_ui.cc:62 +msgid "Soundfile Library" +msgstr "Libreria Audio" + +#: gtk_ardour/library_ui.cc:63 +msgid "Filesystem" +msgstr "" + +#: gtk_ardour/library_ui.cc:66 +msgid "Split Channels" +msgstr "Dividi i Canali" + +#: gtk_ardour/library_ui.cc:69 +msgid "ardour: soundfile selector" +msgstr "ardour: selezione del file audio" + +#: gtk_ardour/library_ui.cc:430 +msgid "Add to Library..." +msgstr "Aggiungi alla libreria..." + +#: gtk_ardour/library_ui.cc:431 +msgid "Remove..." +msgstr "Rimuovi..." + +#: gtk_ardour/library_ui.cc:432 +msgid "Find..." +msgstr "Trova..." + +#: gtk_ardour/library_ui.cc:433 +msgid "Add Folder" +msgstr "Crea una Cartella" + +#: gtk_ardour/library_ui.cc:434 +msgid "Add audio file or directory" +msgstr "Aggiungi un file audio o una cartella" + +#: gtk_ardour/library_ui.cc:713 +msgid "Importing" +msgstr "Importazione" + +#: gtk_ardour/library_ui.cc:748 +msgid "%1 not added to database" +msgstr "%1 non aggiunto al database" + +#: gtk_ardour/library_ui.cc:767 +msgid "Folder name:" +msgstr "Nome della Cartella:" + +#: gtk_ardour/library_ui.cc:838 +msgid "Should not be reached" +msgstr "Impossibile aprire" + +#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096 +msgid "file \"%1\" could not be opened" +msgstr "Impossibile aprire \"%1\"" + +#: gtk_ardour/library_ui.cc:956 +msgid "Field" +msgstr "Campo" + +#: gtk_ardour/library_ui.cc:957 +msgid "Value" +msgstr "Valore" + +#: gtk_ardour/library_ui.cc:973 +msgid "Stop" +msgstr "" + +#: gtk_ardour/library_ui.cc:974 +msgid "Add Field..." +msgstr "Aggiungi Campo" + +#: gtk_ardour/library_ui.cc:975 +msgid "Remove Field" +msgstr "Rimuovi Campo" + +#: gtk_ardour/library_ui.cc:979 +msgid "Soundfile Info" +msgstr "Info sul file audio" + +#: gtk_ardour/library_ui.cc:1106 +msgid "file \"%1\" appears not to be an audio file" +msgstr "" + +#: gtk_ardour/library_ui.cc:1159 +msgid "Could not read file: %1 (%2)." +msgstr "Editor: impossibile aprire il file %1 (%2)." + +#: gtk_ardour/library_ui.cc:1177 +msgid "Could not access soundfile: " +msgstr "Impossibile accedere al file audio" + +#: gtk_ardour/library_ui.cc:1222 +msgid "Field name:" +msgstr "Nome del campo:" + +#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367 +msgid "Field value:" +msgstr "Valore del campo" + +#: gtk_ardour/library_ui.cc:1295 +msgid "Find" +msgstr "Trova" + +#: gtk_ardour/library_ui.cc:1296 +msgid "AND" +msgstr "E" + +#: gtk_ardour/library_ui.cc:1297 +msgid "OR" +msgstr "O" + +#: gtk_ardour/library_ui.cc:1300 +msgid "ardour: locate soundfiles" +msgstr "ardour: localizza file audio" + +#: gtk_ardour/library_ui.cc:1426 +msgid "Results" +msgstr "Risultati" + +#: gtk_ardour/library_ui.cc:1427 +msgid "Uris" +msgstr "Uri" + +#: gtk_ardour/library_ui.cc:1439 +msgid "Create multi-channel region" +msgstr "Crea regione a più canali" + +#: gtk_ardour/library_ui.cc:1442 +msgid "Ardour: Search Results" +msgstr "Ardour: Risultati della Ricerca" + +#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50 +msgid "Set" +msgstr "Imposta" + +#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51 +msgid "Go" +msgstr "Vai" + +#: gtk_ardour/location_ui.cc:54 +msgid "CD" +msgstr "" + +#: gtk_ardour/location_ui.cc:55 +msgid "Hidden" +msgstr "Nascosto" + +#: gtk_ardour/location_ui.cc:57 +msgid "SCMS" +msgstr "" + +#: gtk_ardour/location_ui.cc:58 +msgid "Pre-Emphasis" +msgstr "" + +#: gtk_ardour/location_ui.cc:592 +msgid "Add New Location" +msgstr "Aggiungi una nuova Posizione" + +#: gtk_ardour/location_ui.cc:593 +msgid "Add New Range" +msgstr "Aggiungi un nuovo Intervallo" + +#: gtk_ardour/location_ui.cc:597 +msgid "ardour: locations" +msgstr "ardour: posizioni" + +#: gtk_ardour/location_ui.cc:598 +msgid "ardour_locations" +msgstr "ardour_posizioni" + +#: gtk_ardour/location_ui.cc:629 +#, fuzzy +msgid "Location (CD Index) Markers" +msgstr "Marcatori di posizione" + +#: gtk_ardour/location_ui.cc:649 +#, fuzzy +msgid "Range (CD Track) Markers" +msgstr "Marcatori di intervallo" + +#: gtk_ardour/location_ui.cc:814 +msgid "add range marker" +msgstr "agggiungi marcatore di intervallo" + +#: gtk_ardour/main.cc:76 +msgid "ardour is killing itself for a clean exit\n" +msgstr "ardour sta forzando la chiusura per un'uscita pulita\n" + +#: gtk_ardour/main.cc:85 +msgid "stopping user interface\n" +msgstr "chiusura dell'interfaccia\n" + +#: gtk_ardour/main.cc:104 +#, fuzzy, c-format +msgid "%d(%d): received signal %d\n" +msgstr "%d: ricevuto segnale %d\n" + +#: gtk_ardour/main.cc:190 +msgid "cannot become new process group leader (%1)" +msgstr "" + +#: gtk_ardour/main.cc:217 +msgid "cannot setup signal handling for %1" +msgstr "" + +#: gtk_ardour/main.cc:228 +msgid "cannot set default signal mask (%1)" +msgstr "" + +#: gtk_ardour/main.cc:253 +#, fuzzy +msgid "" +"Without a UI style file, ardour will look strange.\n" +" Please set ARDOUR_UI_RC to point to a valid UI style file" +msgstr "" +"Senza uno Stile per l'Interfaccia, ardour apparirà strano\n" +"Impostare la variabile ARDOUR_UI_RC per puntare ad uno Stile" + +#: gtk_ardour/main.cc:292 +msgid "" +"Ardour could not connect to JACK.\n" +"There are several possible reasons:\n" +"\n" +"1) JACK is not running.\n" +"2) JACK is running as another user, perhaps root.\n" +"3) There is already another client called \"ardour\".\n" +"\n" +"Please consider the possibilities, and perhaps (re)start JACK." +msgstr "" + +#: gtk_ardour/main.cc:305 +msgid "ardour: unplugged" +msgstr "ardour: scollegato" + +#: gtk_ardour/main.cc:363 +msgid "Ardour/GTK " +msgstr "" + +#: gtk_ardour/main.cc:365 +msgid "" +"\n" +" (built using " +msgstr "" + +#: gtk_ardour/main.cc:369 +#, fuzzy +msgid " with libardour " +msgstr " con libardour " + +#: gtk_ardour/main.cc:374 +msgid " and GCC version " +msgstr "" + +#: gtk_ardour/main.cc:384 +msgid "Copyright (C) 1999-2005 Paul Davis" +msgstr "" + +#: gtk_ardour/main.cc:385 +msgid "" +"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel " +"Baker" +msgstr "" + +#: gtk_ardour/main.cc:387 +msgid "Ardour comes with ABSOLUTELY NO WARRANTY" +msgstr "" + +#: gtk_ardour/main.cc:388 +msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +msgstr "" + +#: gtk_ardour/main.cc:389 +msgid "This is free software, and you are welcome to redistribute it " +msgstr "" + +#: gtk_ardour/main.cc:390 +msgid "under certain conditions; see the source for copying conditions." +msgstr "" + +#: gtk_ardour/main.cc:399 +msgid "could not create ARDOUR GUI" +msgstr "Impossibile creare l'interfaccia di Ardour" + +#: gtk_ardour/main.cc:419 +msgid "Could not connect to JACK server as \"%1\"" +msgstr "" + +#: gtk_ardour/main.cc:424 +msgid "could not initialize Ardour." +msgstr "impossibile avviare Ardour" + +#: gtk_ardour/main.cc:435 +msgid "could not load command line session \"%1\"" +msgstr "Impossibile caricare la sessione \"%1\" da linea di comando" + +#: gtk_ardour/main.cc:455 +msgid "" +"\n" +"\n" +"A session named \"%1\" already exists.\n" +"To avoid this message, start ardour as \"ardour %1" +msgstr "" + +#: gtk_ardour/main.cc:466 +msgid "" +"\n" +"\n" +"No session named \"%1\" exists.\n" +"To create it from the command line, start ardour as \"ardour --new %1" +msgstr "" + +#: gtk_ardour/marker.cc:354 +#, fuzzy +msgid "MarkerText" +msgstr "Marcatori" + +#: gtk_ardour/marker_time_axis.cc:271 +#, fuzzy +msgid "Remove Marker" +msgstr "rimuovi marcatore" + +#: gtk_ardour/marker_time_axis.cc:273 +#, fuzzy +msgid "Marker" +msgstr "Marcatori" + +#: gtk_ardour/meter_bridge.cc:74 +msgid "ardour: meter bridge" +msgstr "" + +#: gtk_ardour/meter_bridge.cc:75 +msgid "ardour_meter_bridge" +msgstr "" + +#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93 +#, c-format +msgid "# of %u-sample overs" +msgstr "" + +#: gtk_ardour/meter_bridge_strip.cc:219 +msgid "New name for meter:" +msgstr "Nuovo nome per il meter:" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507 +#: gtk_ardour/region_editor.cc:45 +msgid "mute" +msgstr "muto" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508 +msgid "solo" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506 +msgid "RECORD" +msgstr "REGISTRA" + +#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514 +msgid "polarity" +msgstr "polarità" + +#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509 +msgid "comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810 +msgid "INPUT" +msgstr "ENTRATA" + +#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831 +msgid "OUTPUT" +msgstr "USCITA" + +#: gtk_ardour/mixer_strip.cc:173 +msgid "Pan automation mode" +msgstr "Modalita' automazione pan" + +#: gtk_ardour/mixer_strip.cc:174 +msgid "Gain automation mode" +msgstr "Modalita' automazione gain" + +#: gtk_ardour/mixer_strip.cc:176 +msgid "Pan automation type" +msgstr "Tipo di automazione pan" + +#: gtk_ardour/mixer_strip.cc:177 +msgid "Gain automation type" +msgstr "Tipo di automazione gain" + +#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232 +#: gtk_ardour/mixer_strip.cc:979 +msgid "trim" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233 +#: gtk_ardour/mixer_strip.cc:983 +msgid "abs" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:240 +msgid "gain automation mode" +msgstr "modalita' di automazione gain" + +#: gtk_ardour/mixer_strip.cc:241 +msgid "pan automation mode" +msgstr "modalita' di automazione pan" + +#: gtk_ardour/mixer_strip.cc:242 +msgid "gain automation state" +msgstr "stato dell'automazione gain" + +#: gtk_ardour/mixer_strip.cc:243 +msgid "pan automation state" +msgstr "stato dell'automazione pan" + +#: gtk_ardour/mixer_strip.cc:259 +msgid "varispeed" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174 +msgid "click to add/edit comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:463 +msgid "unknown strip width \"%1\" in XML GUI information" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:522 +msgid "REC" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:525 +#, fuzzy +msgid "cmt" +msgstr "taglia" + +#: gtk_ardour/mixer_strip.cc:530 +msgid "pol" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620 +#: gtk_ardour/redirect_box.cc:1180 +msgid "Not connected to JACK - no I/O changes are possible" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667 +msgid "could not register new ports required for that connection" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:813 +msgid "IN" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:834 +msgid "OUT" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:950 +msgid "aplay" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:956 +msgid "awrite" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:1134 +#, fuzzy +msgid ": comment editor" +msgstr "IU: impossibile avviare l'editor" + +#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224 +msgid "no group" +msgstr "nessun gruppo" + +#: gtk_ardour/mixer_strip.cc:1227 +msgid "~G" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:52 +msgid "Strips" +msgstr "Strisce" + +#: gtk_ardour/mixer_ui.cc:56 +msgid "Snapshots" +msgstr "Istantanee" + +#: gtk_ardour/mixer_ui.cc:61 +msgid "***" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17 +#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144 +#: gtk_ardour/tempo_dialog.cc:162 +msgid "Bar" +msgstr "Battuta" + +#: gtk_ardour/mixer_ui.cc:121 +msgid "Mix Groups" +msgstr "Gruppi di mixaggio" + +#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373 +msgid "ardour: mixer" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:192 +msgid "ardour_mixer" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:342 +msgid "ardour: mixer: " +msgstr "" + +#: gtk_ardour/mixer_ui.cc:641 +msgid "signal" +msgstr "segnale" + +#: gtk_ardour/mixer_ui.cc:672 +msgid "Show All AudioTrack MixerStrips" +msgstr "Mostra tutte le Tracce del Mixer" + +#: gtk_ardour/mixer_ui.cc:673 +msgid "Hide All AudioTrack MixerStrips" +msgstr "Nascondi tutte le Tracce del Mixer" + +#: gtk_ardour/mixer_ui.cc:674 +msgid "Show All AudioBus MixerStrips" +msgstr "Mostra tutti i Bus del Mixer" + +#: gtk_ardour/mixer_ui.cc:675 +msgid "Hide All AudioBus MixerStrips" +msgstr "Nascondi tutti i Bus del Mixer" + +#: gtk_ardour/mixer_ui.cc:687 +msgid "track display list item for renamed strip not found!" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:700 +msgid "Name for new mix group" +msgstr "Nome del nuovo gruppo di mixaggio" + +#: gtk_ardour/new_session_dialog.cc:39 +msgid "Session name:" +msgstr "Nome della sessione:" + +#: gtk_ardour/new_session_dialog.cc:39 +msgid "Create" +msgstr "Crea" + +#: gtk_ardour/new_session_dialog.cc:40 +msgid "use control outs" +msgstr "utilizza le uscite di controllo" + +#: gtk_ardour/new_session_dialog.cc:41 +msgid "use master outs" +msgstr "utilizza le uscite master" + +#: gtk_ardour/new_session_dialog.cc:42 +#, fuzzy +msgid "automatically connect track inputs to physical ports" +msgstr "autoconnetti le entrate delle tracce alle entrate fisiche" + +#: gtk_ardour/new_session_dialog.cc:43 +#, fuzzy +msgid "automatically connect track outputs to master outs" +msgstr "autoconnetti le uscite delle tracce alle uscite master" + +#: gtk_ardour/new_session_dialog.cc:44 +#, fuzzy +msgid "automatically connect track outputs to physical ports" +msgstr "autoconnetti le uscite delle tracce alle uscite fisiche" + +#: gtk_ardour/new_session_dialog.cc:45 +msgid "manually connect track outputs" +msgstr "connetti manualmente le uscite delle tracce" + +#: gtk_ardour/new_session_dialog.cc:50 +msgid "Advanced..." +msgstr "Avanzate..." + +#: gtk_ardour/new_session_dialog.cc:52 +msgid "show again" +msgstr "mostra ancora" + +#: gtk_ardour/new_session_dialog.cc:55 +msgid "Hardware Inputs: use" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:56 +msgid "Hardware Outputs: use" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:62 +msgid "new session setup" +msgstr "impostazione di nuova sessione" + +#: gtk_ardour/new_session_dialog.cc:63 +msgid "ardour_new_session" +msgstr "ardour_nuova_sessione" + +#: gtk_ardour/new_session_dialog.cc:72 +msgid "This session will playback and record at %1 Hz" +msgstr "Questa sessione suonera' e registrera' a %1 Hz" + +#: gtk_ardour/new_session_dialog.cc:74 +msgid "" +"This rate is set by JACK and cannot be changed.\n" +"If you want to use a different sample rate\n" +"please exit and restart JACK" +msgstr "" +"Questo e' impostato da JACK e non pu essere cambiato.\n" +"Se si vuole utilizzare un sample rate differente\n" +"bisogna chiudere e riavviare JACK" + +#: gtk_ardour/new_session_dialog.cc:155 +#, fuzzy +msgid "Session template" +msgstr "usa un modello esistente" + +#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20 +#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146 +#: gtk_ardour/tempo_dialog.cc:164 +msgid "Location" +msgstr "Posizione" + +#: gtk_ardour/new_session_dialog.cc:178 +msgid "Configuration" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:269 +msgid "blank" +msgstr "vuoto" + +#: gtk_ardour/new_session_dialog.cc:328 +msgid "No template - create tracks/busses manually" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:337 +#, fuzzy +msgid "No template" +msgstr "-modello" + +#: gtk_ardour/option_editor.cc:48 +msgid "Internal" +msgstr "interno" + +#: gtk_ardour/option_editor.cc:49 +#, fuzzy +msgid "Slave to MTC" +msgstr "Invia MTC" + +#: gtk_ardour/option_editor.cc:50 +msgid "Sync with JACK" +msgstr "" + +#: gtk_ardour/option_editor.cc:51 +msgid "never used but stops crashes" +msgstr "" + +#: gtk_ardour/option_editor.cc:56 +#, fuzzy +msgid "Later regions are higher" +msgstr "Porta la regione giù di un livello" + +#: gtk_ardour/option_editor.cc:57 +msgid "Most recently added/moved/trimmed regions are higher" +msgstr "" + +#: gtk_ardour/option_editor.cc:58 +#, fuzzy +msgid "Most recently added regions are higher" +msgstr "Porta la regione giù di un livello" + +#: gtk_ardour/option_editor.cc:63 +#, fuzzy +msgid "Span entire region overlap" +msgstr "Porta la regione su di un livello" + +#: gtk_ardour/option_editor.cc:64 +msgid "Short fades at the start of the overlap" +msgstr "" + +#: gtk_ardour/option_editor.cc:82 +#, fuzzy +msgid "Automatically create crossfades" +msgstr "Smorzamento incrociato automatico in caso sovrapposizione" + +#: gtk_ardour/option_editor.cc:83 +msgid "New full-overlap crossfades are unmuted" +msgstr "" + +#: gtk_ardour/option_editor.cc:84 +#, fuzzy +msgid "Region layering mode" +msgstr "Regioni/fine" + +#: gtk_ardour/option_editor.cc:85 +#, fuzzy +msgid "Crossfade model" +msgstr "Smorzamento Incrociato" + +#: gtk_ardour/option_editor.cc:90 +msgid "Latched solo" +msgstr "" + +#: gtk_ardour/option_editor.cc:91 +msgid "Solo via bus" +msgstr "" + +#: gtk_ardour/option_editor.cc:96 +msgid "Show waveforms while recording" +msgstr "Mostra le forme Wave in registrazione" + +#: gtk_ardour/option_editor.cc:97 +msgid "Narrow mixer strips" +msgstr "Strisce del Mixer strette" + +#: gtk_ardour/option_editor.cc:98 +msgid "Show measure lines" +msgstr "Mostra le linee delle Misure" + +#: gtk_ardour/option_editor.cc:99 +msgid "Follow playhead" +msgstr "Segui il cursore" + +#: gtk_ardour/option_editor.cc:103 +msgid "Send MTC" +msgstr "Invia MTC" + +#: gtk_ardour/option_editor.cc:104 +msgid "Send MMC" +msgstr "Invia MMC" + +#: gtk_ardour/option_editor.cc:105 +msgid "JACK time master" +msgstr "" + +#: gtk_ardour/option_editor.cc:107 +msgid "SMPTE offset is negative" +msgstr "" + +#: gtk_ardour/option_editor.cc:111 +msgid "Send MIDI parameter feedback" +msgstr "" + +#: gtk_ardour/option_editor.cc:112 +msgid "MIDI parameter control" +msgstr "" + +#: gtk_ardour/option_editor.cc:113 +#, fuzzy +msgid "MMC control" +msgstr "Porta MMC" + +#: gtk_ardour/option_editor.cc:131 +#, fuzzy +msgid "Auto-connect new track inputs to hardware" +msgstr "Connetti automaticamente nuove tracce" + +#: gtk_ardour/option_editor.cc:132 +#, fuzzy +msgid "Auto-connect new track outputs to hardware" +msgstr "Connetti automaticamente nuove tracce" + +#: gtk_ardour/option_editor.cc:133 +#, fuzzy +msgid "Auto-connect new track outputs to master bus" +msgstr "autoconnetti le uscite delle tracce alle uscite master" + +#: gtk_ardour/option_editor.cc:134 +#, fuzzy +msgid "Manually connect new track outputs" +msgstr "connetti manualmente le uscite delle tracce" + +#: gtk_ardour/option_editor.cc:135 +msgid "Use Hardware Monitoring" +msgstr "Usa il Monitoraggio Hardware" + +#: gtk_ardour/option_editor.cc:136 +msgid "Use Software Monitoring" +msgstr "Usa il Monitoraggio Software" + +#: gtk_ardour/option_editor.cc:137 +msgid "Stop plugins with transport" +msgstr "Ferma i plugin durante il transport" + +#: gtk_ardour/option_editor.cc:138 +msgid "Run plugins while recording" +msgstr "Avvia i plugin durante la registrazione" + +#: gtk_ardour/option_editor.cc:139 +#, fuzzy +msgid "Verify remove last capture" +msgstr "Rimuovi l'ultima registrazione" + +#: gtk_ardour/option_editor.cc:140 +msgid "Stop recording on xrun" +msgstr "Ferma la registrazione in caso di xrun" + +#: gtk_ardour/option_editor.cc:141 +msgid "Stop transport at end of session" +msgstr "Ferma il transport a fine sessione" + +#: gtk_ardour/option_editor.cc:142 +msgid "Debug keyboard events" +msgstr "" + +#: gtk_ardour/option_editor.cc:143 +msgid "-12dB gain reduction for ffwd/rew" +msgstr "" + +#: gtk_ardour/option_editor.cc:152 +msgid "ardour: options editor" +msgstr "ardour: editor delle opzioni" + +#: gtk_ardour/option_editor.cc:153 +msgid "ardour_option_editor" +msgstr "ardour_editor_delle_opzioni" + +#: gtk_ardour/option_editor.cc:183 +msgid "Misc" +msgstr "Varie" + +#: gtk_ardour/option_editor.cc:184 +msgid "Sync" +msgstr "" + +#: gtk_ardour/option_editor.cc:185 +msgid "Paths/Files" +msgstr "Percorsi/File" + +#: gtk_ardour/option_editor.cc:186 +msgid "Display" +msgstr "Interfaccia" + +#: gtk_ardour/option_editor.cc:187 +msgid "Kbd/Mouse" +msgstr "Tastiera/Mouse" + +#: gtk_ardour/option_editor.cc:188 +msgid "Click" +msgstr "" + +#: gtk_ardour/option_editor.cc:190 +msgid "Layers & Fades" +msgstr "" + +#: gtk_ardour/option_editor.cc:195 +msgid "MIDI" +msgstr "" + +#: gtk_ardour/option_editor.cc:268 +msgid "24 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:270 +msgid "25 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:272 +msgid "30 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:278 +msgid "30 FPS drop" +msgstr "" + +#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379 +#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736 +#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800 +msgid "Medium" +msgstr "" + +#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738 +#: gtk_ardour/option_editor.cc:804 +#, fuzzy +msgid "Faster" +msgstr "Veloce" + +#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714 +#: gtk_ardour/option_editor.cc:776 +#, fuzzy +msgid "Short" +msgstr "entrata" + +#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716 +#: gtk_ardour/option_editor.cc:780 +msgid "Long" +msgstr "" + +#: gtk_ardour/option_editor.cc:396 +msgid "Broadcast WAVE/floating point" +msgstr "" + +#: gtk_ardour/option_editor.cc:397 +msgid "WAVE/floating point" +msgstr "" + +#: gtk_ardour/option_editor.cc:417 +msgid "session RAID path" +msgstr "Percorso RAID della sessione" + +#: gtk_ardour/option_editor.cc:422 +msgid "Native Format" +msgstr "Formato Nativo" + +#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460 +#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409 +msgid "internal" +msgstr "interno" + +#: gtk_ardour/option_editor.cc:537 +msgid "Short crossfade length (msecs)" +msgstr "" + +#: gtk_ardour/option_editor.cc:710 +msgid "Meter Peak Hold" +msgstr "" + +#: gtk_ardour/option_editor.cc:730 +msgid "Meter Falloff" +msgstr "" + +#: gtk_ardour/option_editor.cc:847 +msgid "Positional Sync" +msgstr "" + +#: gtk_ardour/option_editor.cc:902 +msgid "SMPTE Frames/second" +msgstr "" + +#: gtk_ardour/option_editor.cc:903 +msgid "SMPTE Offset" +msgstr "" + +#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013 +#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211 +#, fuzzy +msgid "online" +msgstr "lineare" + +#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014 +#: gtk_ardour/option_editor.cc:1208 +#, fuzzy +msgid "offline" +msgstr "lineare" + +#: gtk_ardour/option_editor.cc:1319 +msgid "Use as click" +msgstr "Usa come click" + +#: gtk_ardour/option_editor.cc:1344 +msgid "Use as click emphasis" +msgstr "Usa come enfasi del click" + +#: gtk_ardour/option_editor.cc:1478 +msgid "--unknown--" +msgstr "--sconosciuto--" + +#: gtk_ardour/option_editor.cc:1595 +msgid "Click audio file" +msgstr "File audio del click" + +#: gtk_ardour/option_editor.cc:1601 +msgid "Click emphasis audiofile" +msgstr "Pecorso del file di enfasi click" + +#: gtk_ardour/option_editor.cc:1638 +msgid "" +"The auditioner is a dedicated mixer strip used\n" +"for listening to specific regions outside the context\n" +"of the overall mix. It can be connected just like any\n" +"other mixer strip." +msgstr "" +"L'auditioner è una speciale striscia del mixer,\n" +"usata per ascoltare specifiche regioni al di fuori\n" +"del contesto del mixaggio. Può essere connessa proprio\n" +"come ogni altra striscia del mixer." + +#: gtk_ardour/option_editor.cc:1887 +msgid "Edit using" +msgstr "Modifica usando" + +#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924 +msgid "+ button" +msgstr "+ pulsante" + +#: gtk_ardour/option_editor.cc:1917 +msgid "Delete using" +msgstr "Elimina usando" + +#: gtk_ardour/option_editor.cc:1947 +msgid "Ignore snap using" +msgstr "Ignora l'allineamento automatico usando" + +#: gtk_ardour/opts.cc:46 +msgid "Usage: " +msgstr "Utilizzo: " + +#: gtk_ardour/opts.cc:47 +msgid " -v, --version Show version information\n" +msgstr " -v, --versione Mostra info sulla versione\n" + +#: gtk_ardour/opts.cc:48 +msgid " -h, --help Print this message\n" +msgstr " -h, --help Mostra questo messaggio\n" + +#: gtk_ardour/opts.cc:49 +msgid "" +" -b, --bindings Print all possible keyboard binding " +"names\n" +msgstr "" +" -b, --bindings Mostra tutte le possibili combinazioni di " +"tasti\n" + +#: gtk_ardour/opts.cc:50 +#, fuzzy +msgid " -n, --show-splash Show splash screen\n" +msgstr "" +" -n, --no-splash Non mostrare la schermata d'avvio\n" + +#: gtk_ardour/opts.cc:51 +#, fuzzy +msgid "" +" -c, --name name Use a specific jack client name, default " +"is ardour\n" +msgstr "" +" -c, --jack-client-name name Utilizza nome specifico per jack, " +"predefinito e' ardour\n" + +#: gtk_ardour/opts.cc:52 +#, fuzzy +msgid "" +" -N, --new session-name Create a new session from the command " +"line\n" +msgstr " [nome sessione] Nome della sessione da caricare\n" + +#: gtk_ardour/opts.cc:53 +msgid "" +" -o, --use-hw-optimizations Try to use h/w specific optimizations\n" +msgstr "" + +#: gtk_ardour/opts.cc:55 +#, fuzzy +msgid " -V, --novst Do not use VST support\n" +msgstr "" +" -n, --no-splash Non mostrare la schermata d'avvio\n" + +#: gtk_ardour/opts.cc:57 +msgid " [session-name] Name of session to load\n" +msgstr " [nome sessione] Nome della sessione da caricare\n" + +#: gtk_ardour/opts.cc:58 +msgid " -C, --curvetest filename Curve algorithm debugger\n" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:58 +msgid "You can't graphically edit panning of more than stream" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:78 +#, fuzzy +msgid "add pan automation event" +msgstr "aggiungi evento di automazione a " + +#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441 +#, fuzzy +msgid "Bypass" +msgstr "Battute" + +#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222 +#, fuzzy +msgid "link" +msgstr "vuoto" + +#: gtk_ardour/panner_ui.cc:103 +msgid "panning link control" +msgstr "" + +#: gtk_ardour/panner_ui.cc:105 +msgid "panning link direction" +msgstr "" + +#: gtk_ardour/panner_ui.cc:232 +msgid "L" +msgstr "" + +#: gtk_ardour/panner_ui.cc:344 +#, c-format +msgid "panner for channel %u" +msgstr "" + +#: gtk_ardour/panner_ui.cc:451 +#, fuzzy +msgid "Reset all" +msgstr "azzera" + +#: gtk_ardour/playlist_selector.cc:46 +msgid "Playlists grouped by track" +msgstr "" + +#: gtk_ardour/playlist_selector.cc:53 +#, fuzzy +msgid "close" +msgstr "Chiudi" + +#: gtk_ardour/playlist_selector.cc:59 +#, fuzzy +msgid "ardour: playlists" +msgstr "azzera le posizioni" + +#: gtk_ardour/playlist_selector.cc:104 +#, fuzzy +msgid "ardour: playlist for " +msgstr "ardour: editor delle opzioni" + +#: gtk_ardour/playlist_selector.cc:122 +#, fuzzy +msgid "Other tracks" +msgstr "Nascondi traccia" + +#: gtk_ardour/playlist_selector.cc:138 +msgid "unassigned" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:41 +msgid "Available LADSPA plugins" +msgstr "Plugin LADSPA disponibili" + +#: gtk_ardour/plugin_selector.cc:42 +msgid "Type" +msgstr "Tipo" + +#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51 +msgid "# Inputs" +msgstr "# Entrate" + +#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52 +msgid "# Outputs" +msgstr "# Uscite" + +#: gtk_ardour/plugin_selector.cc:50 +msgid "Available VST plugins" +msgstr "Plugin VST disponibili" + +#: gtk_ardour/plugin_selector.cc:58 +msgid "To be added" +msgstr "Da aggiungere" + +#: gtk_ardour/plugin_selector.cc:72 +msgid "ardour: plugins" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:82 +msgid "Add a plugin to the effect list" +msgstr "Aggiungi un plugin alla lista degli effetti" + +#: gtk_ardour/plugin_selector.cc:84 +msgid "Remove a plugin from the effect list" +msgstr "Rimuovi un plugin dalla lista degli effetti" + +#: gtk_ardour/plugin_selector.cc:88 +msgid "Update" +msgstr "Aggiorna" + +#: gtk_ardour/plugin_selector.cc:89 +msgid "Update available plugins" +msgstr "Aggiorna i plugin disponibili" + +#: gtk_ardour/plugin_selector.cc:110 +msgid "LADSPA" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:113 +msgid "VST" +msgstr "VST" + +#: gtk_ardour/plugin_ui.cc:83 +msgid "" +"unknown type of editor-supplying plugin (note: no VST support in this " +"version of ardour)" +msgstr "" +"tipo di plugin fornito sconosciuto (nota: nessun supporto a VST in questa " +"versione di ardour)" + +#: gtk_ardour/plugin_ui.cc:269 +msgid "Plugin Editor: could not build control element for port %1" +msgstr "" +"Plugin Editor: impossibile creare elemento di controllo per la porta %1" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "in" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "ins" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "out" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "outs" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:382 +msgid "automation control" +msgstr "controllo di automazione" + +#: gtk_ardour/plugin_ui.cc:869 +#, fuzzy +msgid "save" +msgstr "Salva" + +#: gtk_ardour/plugin_ui.cc:870 +msgid "bypass" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:892 +msgid "Plugin preset %1 not found" +msgstr "Preset per plugin %1 non trovato" + +#: gtk_ardour/plugin_ui.cc:903 +msgid "Name for plugin settings:" +msgstr "Nome per le impostazioni del plugin" + +#: gtk_ardour/redirect_automation_line.cc:53 +msgid "redirect automation created for non-plugin" +msgstr "automazione di redirect creata per non-plugin" + +#: gtk_ardour/redirect_automation_time_axis.cc:92 +msgid "add automation event to " +msgstr "aggiungi evento di automazione a " + +#: gtk_ardour/redirect_box.cc:213 +msgid "New send" +msgstr "" + +#: gtk_ardour/redirect_box.cc:214 +#, fuzzy +msgid "Show send controls" +msgstr "utilizza le uscite di controllo" + +#: gtk_ardour/redirect_box.cc:360 +msgid "New Plugin ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:361 +#, fuzzy +msgid "New Insert" +msgstr "Nuova entrata" + +#: gtk_ardour/redirect_box.cc:362 +msgid "New Send ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:380 +#, fuzzy +msgid "Select all" +msgstr "Seleziona tutto" + +#: gtk_ardour/redirect_box.cc:381 +#, fuzzy +msgid "Deselect all" +msgstr "Seleziona tutto" + +#: gtk_ardour/redirect_box.cc:389 +#, fuzzy +msgid "Inserts" +msgstr "Inverti" + +#: gtk_ardour/redirect_box.cc:390 +#, fuzzy +msgid "Sends" +msgstr "Secondi" + +#: gtk_ardour/redirect_box.cc:393 +#, fuzzy +msgid "Select all ..." +msgstr "Seleziona tutto" + +#: gtk_ardour/redirect_box.cc:406 +#, fuzzy +msgid "Activate All" +msgstr "Attiva" + +#: gtk_ardour/redirect_box.cc:407 +#, fuzzy +msgid "Deactivate All" +msgstr "Disattiva" + +#: gtk_ardour/redirect_box.cc:488 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point, there are\n" +"%3 active signal streams.\n" +"\n" +"This makes no sense - you are throwing away\n" +"part of the signal." +msgstr "" + +#: gtk_ardour/redirect_box.cc:500 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point there are\n" +"only %3 active signal streams.\n" +"\n" +"This makes no sense - unless the plugin supports\n" +"side-chain inputs. A future version of Ardour will\n" +"support this type of configuration." +msgstr "" + +#: gtk_ardour/redirect_box.cc:513 +msgid "" +"You attempted to add a plugin (%1).\n" +"\n" +"The I/O configuration doesn't make sense:\n" +"\n" +"The plugin has %2 inputs and %3 outputs.\n" +"The track/bus has %4 inputs and %5 outputs.\n" +"The insertion point, has %6 active signals.\n" +"\n" +"Ardour does not understand what to do in such situations.\n" +msgstr "" + +#: gtk_ardour/redirect_box.cc:616 +msgid "Pre-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:619 +msgid "Post-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:781 +msgid "" +"You cannot reorder this set of redirects\n" +"in that way because the inputs and\n" +"outputs do not work correctly." +msgstr "" + +#: gtk_ardour/redirect_box.cc:903 +#, fuzzy +msgid "ardour: rename redirect" +msgstr "ardour: rinomina la regione" + +#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043 +msgid "" +"Copying the set of redirects on the clipboard failed,\n" +"probably because the I/O configuration of the plugins\n" +"could not match the configuration of this track." +msgstr "" + +#: gtk_ardour/redirect_box.cc:1064 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this track?\n" +"(this cannot be undone)" +msgstr "" +"Si vuole realmente rimuovere la traccia \"%1\" ?\n" +"(questa azione non potrà essere annullata)" + +#: gtk_ardour/redirect_box.cc:1067 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this bus?\n" +"(this cannot be undone)" +msgstr "" +"Si vuole realmente rimuovere la traccia \"%1\" ?\n" +"(questa azione non potrà essere annullata)" + +#: gtk_ardour/redirect_box.cc:1071 +#, fuzzy +msgid "Yes, remove them all" +msgstr "Si, rimuovi." + +#: gtk_ardour/redirect_box.cc:1114 +#, fuzzy +msgid "ardour: %1" +msgstr "ardour: orologio" + +#: gtk_ardour/redirect_box.cc:1156 +#, fuzzy +msgid "ardour: %1: %2 (by %3)" +msgstr "ardour: regione" + +#: gtk_ardour/region_editor.cc:43 +msgid "NAME:" +msgstr "NOME:" + +#: gtk_ardour/region_editor.cc:44 +msgid "lock" +msgstr "blocca" + +#: gtk_ardour/region_editor.cc:46 +msgid "opaque" +msgstr "opaco" + +#: gtk_ardour/region_editor.cc:49 +msgid "Layer" +msgstr "Livello" + +#: gtk_ardour/region_editor.cc:57 +msgid "ENVELOPE" +msgstr "" + +#: gtk_ardour/region_editor.cc:108 +msgid "mute this region" +msgstr "Metti in muto questa regione" + +#: gtk_ardour/region_editor.cc:109 +msgid "regions underneath this one cannot be heard" +msgstr "le regioni al di sotto di questa non posssono essere udite" + +#: gtk_ardour/region_editor.cc:110 +msgid "prevent any changes to this region" +msgstr "impedisci qualsiasi cambio a questa regione" + +#: gtk_ardour/region_editor.cc:111 +msgid "use the gain envelope during playback" +msgstr "usa la curva di gain suonando" + +#: gtk_ardour/region_editor.cc:112 +msgid "show the gain envelope" +msgstr "mostra la curva di gain" + +#: gtk_ardour/region_editor.cc:113 +msgid "use fade in curve during playback" +msgstr "usa la curva di smorzamento in entrata, suonando" + +#: gtk_ardour/region_editor.cc:114 +msgid "use fade out curve during playback" +msgstr "usa la curva di smorzamento in uscita, suonando" + +#: gtk_ardour/region_editor.cc:115 +msgid "audition this region" +msgstr "fai l'audition di questa regione" + +#: gtk_ardour/region_editor.cc:148 +msgid "START:" +msgstr "INIZIO:" + +#: gtk_ardour/region_editor.cc:150 +msgid "END:" +msgstr "FINE" + +#: gtk_ardour/region_editor.cc:152 +msgid "LENGTH:" +msgstr "LUNGHEZZA" + +#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198 +#: gtk_ardour/region_editor.cc:234 +msgid "active" +msgstr "attivo" + +#: gtk_ardour/region_editor.cc:179 +msgid "visible" +msgstr "visibile" + +#: gtk_ardour/region_editor.cc:197 +msgid "FADE IN" +msgstr "SMORZA ENTRATA" + +#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235 +msgid "msecs" +msgstr "msec" + +#: gtk_ardour/region_editor.cc:233 +msgid "FADE OUT" +msgstr "SMORZA USCITA" + +#: gtk_ardour/region_editor.cc:276 +msgid "ardour: region " +msgstr "ardour: regione" + +#: gtk_ardour/region_editor.cc:410 +msgid "fade in edit" +msgstr "modifica lo smorzamento in entrata" + +#: gtk_ardour/region_editor.cc:422 +msgid "fade out edit" +msgstr "modifica lo smorzamento in uscita" + +#: gtk_ardour/regionview.cc:1169 +#, fuzzy +msgid "add gain control point" +msgstr "Rimuovi il punto di sincronizzazione" + +#: gtk_ardour/route_params_ui.cc:58 +msgid "Tracks/Buses" +msgstr "Tracce/Bus" + +#: gtk_ardour/route_params_ui.cc:59 +msgid "Pre Redirects" +msgstr "Pre Redirezionamenti" + +#: gtk_ardour/route_params_ui.cc:60 +msgid "Post Redirects" +msgstr "Post Redirezionamenti" + +#: gtk_ardour/route_params_ui.cc:105 +#, fuzzy +msgid "Pre-fader Redirects" +msgstr "Pre Redirezionamenti" + +#: gtk_ardour/route_params_ui.cc:106 +#, fuzzy +msgid "Post-fader Redirects" +msgstr "Post Redirezionamenti" + +#: gtk_ardour/route_params_ui.cc:138 +#, fuzzy +msgid "ardour: track/bus inspector" +msgstr "ardour: aggiungi traccia/bus" + +#: gtk_ardour/route_params_ui.cc:139 +msgid "ardour_route_parameters" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:189 +msgid "route display list item for renamed route not found!" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:448 +msgid "NO TRACK" +msgstr "NESSUNA TRACCIA" + +#: gtk_ardour/route_params_ui.cc:669 +#, fuzzy +msgid "ardour: track/bus inspector: " +msgstr "ardour: aggiungi traccia/bus" + +#: gtk_ardour/route_params_ui.cc:673 +msgid "No Route Selected" +msgstr "Nessun Route Selezionato" + +#: gtk_ardour/route_params_ui.cc:674 +#, fuzzy +msgid "ardour: track/bus/inspector: no route selected" +msgstr "ardour: parametri di route: nessun route selezionato" + +#: gtk_ardour/route_ui.cc:134 +#, fuzzy +msgid "mute change" +msgstr "Imposta l'intervallo di Punch" + +#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220 +#, fuzzy +msgid "solo change" +msgstr "Intervallo di loop" + +#: gtk_ardour/route_ui.cc:284 +msgid "rec-enable change" +msgstr "" + +#: gtk_ardour/route_ui.cc:423 +msgid "Solo-safe" +msgstr "" + +#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474 +msgid "MIDI Bind" +msgstr "" + +#: gtk_ardour/route_ui.cc:445 +msgid "Pre Fader" +msgstr "" + +#: gtk_ardour/route_ui.cc:452 +msgid "Post Fader" +msgstr "" + +#: gtk_ardour/route_ui.cc:459 +msgid "Control Outs" +msgstr "Uscite di Controllo" + +#: gtk_ardour/route_ui.cc:466 +msgid "Main Outs" +msgstr "Uscite Principali" + +#: gtk_ardour/route_ui.cc:503 +msgid "mix group solo change" +msgstr "" + +#: gtk_ardour/route_ui.cc:537 +msgid "mix group mute change" +msgstr "" + +#: gtk_ardour/route_ui.cc:553 +msgid "mix group rec-enable change" +msgstr "" + +#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258 +msgid "ardour: color selection" +msgstr "ardour: selezione del colore" + +#: gtk_ardour/route_ui.cc:652 +#, fuzzy +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"You may also lose the playlist used by this track.\n" +"(cannot be undone)" +msgstr "" +"Si vuole realmente rimuovere la traccia \"%1\" ?\n" +"(questa azione non potrà essere annullata)" + +#: gtk_ardour/route_ui.cc:654 +msgid "" +"Do you really want to remove bus \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Si vuole realmente rimuovere il bus \"%1\" ?\n" +"(questa azione non potrà essere annullata)" + +#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299 +msgid "Yes, remove it." +msgstr "Si, rimuovi." + +#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358 +msgid "new name: " +msgstr "nuovo nome: " + +#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31 +msgid "Beats per minute" +msgstr "Battiti al minuto" + +#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35 +#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163 +msgid "Beat" +msgstr "Battito" + +#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158 +msgid "Meter denominator" +msgstr "Denominatore per il Meter" + +#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159 +msgid "Beats per bar" +msgstr "Battiti per battuta" + +#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189 +msgid "whole (1)" +msgstr "intero (1)" + +#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191 +msgid "second (2)" +msgstr "mezzo (2)" + +#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193 +msgid "third (3)" +msgstr "terzo (3)" + +#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195 +#: gtk_ardour/tempo_dialog.cc:203 +msgid "quarter (4)" +msgstr "quarto (4)" + +#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197 +msgid "eighth (8)" +msgstr "ottavo (8)" + +#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199 +msgid "sixteenth (16)" +msgstr "sedicesimo (16)" + +#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201 +msgid "thirty-second (32)" +msgstr "trentaduesimo (32)" + +#: gtk_ardour/tempo_dialog.cc:301 +msgid "garbaged note type entry (%1)" +msgstr "" + +#: gtk_ardour/tempo_dialog.cc:311 +msgid "incomprehensible note type entry (%1)" +msgstr "" + +#: gtk_ardour/time_axis_view.cc:95 +msgid "gTortnam" +msgstr "" + +#: gtk_ardour/time_axis_view.cc:446 +msgid "Largest" +msgstr "Ampissimo" + +#: gtk_ardour/time_axis_view.cc:447 +msgid "Large" +msgstr "Più ampio" + +#: gtk_ardour/time_axis_view.cc:448 +msgid "Larger" +msgstr "Ampio" + +#: gtk_ardour/time_axis_view.cc:450 +msgid "Smaller" +msgstr "Piccolo" + +#: gtk_ardour/time_axis_view.cc:451 +msgid "Small" +msgstr "Più piccolo" + +#: gtk_ardour/time_axis_view.cc:785 +msgid "unknown track height name \"%1\" in XML GUI information" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:69 +msgid "TimeAxisViewItemName" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:258 +msgid "new duration %1 frames is out of bounds for %2" +msgstr "" + +#: gtk_ardour/time_selection.cc:40 +msgid "programming error: request for non-existent audio range (%1)!" +msgstr "" + +#: gtk_ardour/utils.cc:57 +msgid "" +"\"\n" +"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+=" +msgstr "" + +#: gtk_ardour/utils.cc:66 +msgid "aeiou" +msgstr "" + +#: gtk_ardour/utils.cc:75 +msgid "AEIOU" +msgstr "" + +#: gtk_ardour/utils.cc:84 +msgid "bcdfghjklmnpqrtvwxyz" +msgstr "" + +#: gtk_ardour/utils.cc:93 +msgid "BCDFGHJKLMNPQRTVWXYZ" +msgstr "" + +#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265 +msgid "bad XPM header %1" +msgstr "" + +#: gtk_ardour/utils.cc:516 +msgid "missing RGBA style for \"%1\"" +msgstr "" + +#: gtk_ardour/visual_time_axis.cc:297 +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Si vuole realmente rimuovere la traccia \"%1\" ?\n" +"(questa azione non potrà essere annullata)" + +#: gtk_ardour/visual_time_axis.cc:385 +msgid "A track already exists with that name" +msgstr "esiste già una traccia con quel nome" + +#~ msgid "Export to CD" +#~ msgstr "Esporta a CD" + +#~ msgid "programming error: location/marker map does not contain location!" +#~ msgstr "" +#~ "errore di programmazione: la mappa di posizioni/marcatori non contiene " +#~ "alcuna posizione!" + +#~ msgid "No toggle button pixmaps found to match toggle-button-[0-9]*.xpm$" +#~ msgstr "Impossibile trovare una immagine per toggle-button-[0-9]*.xpm$" + +#~ msgid "" +#~ "No small push button pixmaps found to match small-round-button-[0-9]*.xpm$" +#~ msgstr "Impossibile trovare una immagine per small-round-button-[0-9]*.xpm$" + +#~ msgid "No pixmaps found to match hslider[0-9]*.xpm$" +#~ msgstr "Impossibile trovare una immagine per hslider[0-9]*.xpm$" + +#~ msgid "No pixmaps found to match vslider[0-9]*.xpm$" +#~ msgstr "Impossibile trovare una immagine per vslider[0-9]*.xpm$" + +#~ msgid "Trace MIDI Input" +#~ msgstr "Tieni traccia delle Entrate MIDI" + +#~ msgid "Trace MIDI Output" +#~ msgstr "Tieni traccia delle Uscite MIDI" + +#~ msgid "MTC Port" +#~ msgstr "Porta MTC" + +#~ msgid "attempt to timestretch a non-audio track!" +#~ msgstr "si tenta il timestretch su una traccia non audio!" + +#~ msgid "ardour: tempo editor" +#~ msgstr "ardour: modifica il tempo" + +#~ msgid "ok" +#~ msgstr "Ok" + +#~ msgid "apply" +#~ msgstr "applica" + +#~ msgid "fade" +#~ msgstr "smorzamento" + +#~ msgid "Edit left" +#~ msgstr "Modifica a sinistra" + +#~ msgid "Edit right" +#~ msgstr "Modifica a destra" + +#~ msgid "Edit fade" +#~ msgstr "Modifica smorzamento" + +#~ msgid "Export region" +#~ msgstr "Esporta regione" + +#, fuzzy +#~ msgid "Bounce region" +#~ msgstr "Fai il Bounce dell'intervallo" + +#~ msgid "Region" +#~ msgstr "Regione" + +#~ msgid "Play selected region" +#~ msgstr "Suona la regione selezionata" + +#~ msgid "clear connections" +#~ msgstr "azzera le connessioni" + +#~ msgid "add comments/notes here" +#~ msgstr "aggiungi note/commenti qui" + +#~ msgid "Crossfades in use" +#~ msgstr "Smorzamenti Incrociati in uso" + +#, fuzzy +#~ msgid "outside this computer" +#~ msgstr "Nascondi traccia" + +#, fuzzy +#~ msgid "inside this computer" +#~ msgstr "Nascondi traccia" diff --git a/gtk2_ardour/po/pt_BR.po b/gtk2_ardour/po/pt_BR.po new file mode 100644 index 0000000000..afb3554583 --- /dev/null +++ b/gtk2_ardour/po/pt_BR.po @@ -0,0 +1,5104 @@ +# Ardour Brazilian Portuguese translation file +# Copyright (C) 2003-2004 Paul Davis +# This file is distributed under the same license as the Ardour package. +# Authors: Alexander Franca +# Chris Ross +# Leandro Marco +# +# +msgid "" +msgstr "" +"Project-Id-Version: ardour 0.688.4\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2005-09-19 18:09-0400\n" +"PO-Revision-Date: 2005-08-15 21:50-0000\n" +"Last-Translator: Chris Ross, Alexander Franca & Leandro Marco\n" +"Language-Team: Portuguese\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: gtk_ardour/about.cc:134 +msgid "Marcus Andersson" +msgstr "" + +#: gtk_ardour/about.cc:135 +msgid "Jeremy Hall" +msgstr "" + +#: gtk_ardour/about.cc:136 +msgid "Steve Harris" +msgstr "" + +#: gtk_ardour/about.cc:137 +msgid "Tim Mayberry" +msgstr "" + +#: gtk_ardour/about.cc:138 +msgid "Mark Stewart" +msgstr "" + +#: gtk_ardour/about.cc:139 +msgid "Sam Chessman" +msgstr "" + +#: gtk_ardour/about.cc:140 +msgid "Jack O'Quin" +msgstr "" + +#: gtk_ardour/about.cc:141 +msgid "Matt Krai" +msgstr "" + +#: gtk_ardour/about.cc:142 +msgid "Ben Bell" +msgstr "" + +#: gtk_ardour/about.cc:143 +msgid "Gerard van Dongen" +msgstr "" + +#: gtk_ardour/about.cc:144 +msgid "Thomas Charbonnel" +msgstr "" + +#: gtk_ardour/about.cc:145 +msgid "Nick Mainsbridge" +msgstr "" + +#: gtk_ardour/about.cc:146 +msgid "Colin Law" +msgstr "" + +#: gtk_ardour/about.cc:147 +msgid "Sampo Savolainen" +msgstr "" + +#: gtk_ardour/about.cc:148 +msgid "Joshua Leach" +msgstr "" + +#: gtk_ardour/about.cc:149 +msgid "Rob Holland" +msgstr "" + +#: gtk_ardour/about.cc:150 +msgid "Per Sigmond" +msgstr "" + +#: gtk_ardour/about.cc:151 +msgid "Doug Mclain" +msgstr "" + +#: gtk_ardour/about.cc:156 +msgid "" +"French:\n" +"\tAlain Fréhel " +msgstr "" + +#: gtk_ardour/about.cc:157 +msgid "" +"German:\n" +"\tKarsten Petersen " +msgstr "" + +#: gtk_ardour/about.cc:158 +msgid "" +"Italian:\n" +"\tFilippo Pappalardo " +msgstr "" + +#: gtk_ardour/about.cc:159 +msgid "" +"Portuguese:\n" +"\tRui Nuno Capela " +msgstr "" + +#: gtk_ardour/about.cc:160 +msgid "" +"Brazilian Portuguese:\n" +"\tAlexander da Franca Fernandes \n" +"\tChris Ross " +msgstr "" + +#: gtk_ardour/about.cc:162 +msgid "" +"Spanish:\n" +"\t Alex Krohn " +msgstr "" + +#: gtk_ardour/about.cc:163 +msgid "" +"Russian:\n" +"\t Igor Blinov " +msgstr "" + +#: gtk_ardour/about.cc:181 +msgid "" +"Copyright (C) 1999-2005 Paul Davis\n" +"Ardour comes with ABSOLUTELY NO WARRANTY\n" +"This is free software, and you are welcome to redistribute it\n" +"under certain conditions; see the file COPYING for details.\n" +msgstr "" + +#: gtk_ardour/about.cc:188 +msgid "" +"Ardour: %1\n" +"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)" +msgstr "" +"Ardour: %1\n" +"(construído com ardour/gtk %2.%3.%4 libardour: %5.%6.%7)" + +#: gtk_ardour/about.cc:206 +msgid "" +"Primary author:\n" +"\tPaul Davis\n" +"\n" +"Major developers:\n" +"\tJesse Chappell\n" +"\tTaybin Rutkin\n" +"Contributors:\n" +"\t" +msgstr "" + +#: gtk_ardour/about.cc:243 +msgid "Authors" +msgstr "Autores" + +#: gtk_ardour/about.cc:244 +msgid "Translators" +msgstr "Tradutores" + +#: gtk_ardour/about.cc:361 +msgid "cannot open splash image file \"%1\"" +msgstr "não foi possível abrir o arquivo de imagem \"%1\"" + +#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33 +#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81 +#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977 +#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85 +#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777 +#: gtk_ardour/redirect_box.cc:900 +msgid "OK" +msgstr "OK" + +#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92 +#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046 +#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72 +#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982 +#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733 +#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000 +#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129 +#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785 +#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86 +#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072 +#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33 +#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161 +msgid "Cancel" +msgstr "Cancelar" + +#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94 +msgid "Tracks" +msgstr "Trilhas" + +#: gtk_ardour/add_route_dialog.cc:43 +msgid "Busses" +msgstr "Barramentos" + +#: gtk_ardour/add_route_dialog.cc:48 +msgid "ardour: add track/bus" +msgstr "ardour: adicionar trilhas/barramento" + +#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81 +msgid "Add" +msgstr "Adicionar" + +#: gtk_ardour/add_route_dialog.cc:86 +msgid "Name (template)" +msgstr "Nome (esquema)" + +#: gtk_ardour/ardour_ui.cc:798 +msgid "" +"pre\n" +"roll" +msgstr "" +"pré\n" +"rolagem" + +#: gtk_ardour/ardour_ui.cc:799 +msgid "" +"post\n" +"roll" +msgstr "" +"pós\n" +"rolagem" + +#: gtk_ardour/ardour_ui.cc:807 +msgid "% " +msgstr "" + +#: gtk_ardour/ardour_ui.cc:808 +msgid "spring" +msgstr "pular" + +#: gtk_ardour/ardour_ui.cc:810 +msgid "" +"punch\n" +"in" +msgstr "" +"iniciar\n" +"inserção" + +#: gtk_ardour/ardour_ui.cc:811 +msgid "" +"punch\n" +"out" +msgstr "" +"finalizar\n" +"inserção" + +#: gtk_ardour/ardour_ui.cc:812 +msgid "" +"auto\n" +"return" +msgstr "" +"retorno\n" +"automático" + +#: gtk_ardour/ardour_ui.cc:813 +msgid "" +"auto\n" +"play" +msgstr "" +"reprodução\n" +"automática" + +#: gtk_ardour/ardour_ui.cc:814 +msgid "" +"auto\n" +"input" +msgstr "" +"entrada\n" +"automática" + +#: gtk_ardour/ardour_ui.cc:815 +msgid "click" +msgstr "batimento" + +#: gtk_ardour/ardour_ui.cc:816 +msgid "" +"follow\n" +"PH" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:817 +msgid "AUDITIONING" +msgstr "AUDIÇÃO" + +#: gtk_ardour/ardour_ui.cc:818 +msgid "SOLO" +msgstr "SOLO" + +#: gtk_ardour/ardour_ui.cc:870 +msgid "Percentage" +msgstr "Percentual" + +#: gtk_ardour/ardour_ui.cc:872 +msgid "Semitones" +msgstr "Semitons" + +#: gtk_ardour/ardour_ui.cc:875 +msgid "Sprung" +msgstr "Retornável" + +#: gtk_ardour/ardour_ui.cc:877 +msgid "Wheel" +msgstr "Fixo" + +#: gtk_ardour/ardour_ui.cc:902 +msgid "" +"You cannot record-enable\n" +"track %1\n" +"because it has no input connections.\n" +"You would be wasting space recording silence." +msgstr "" +"Vocãonão pode habilitar para gravaãoo\n" +"a trilha %1\n" +"porque ela não tem conexãos de entrada.\n" +"Você estaria desperdiçando espaço gravando silêncio." + +#: gtk_ardour/ardour_ui.cc:1073 +msgid "quit" +msgstr "sair" + +#: gtk_ardour/ardour_ui.cc:1082 +msgid "" +"Ardour was unable to save your session.\n" +"\n" +"If you still wish to quit, please use the\n" +"\n" +"\"Just quit\" option." +msgstr "" +"Ardour não pôde salvar sua sessão\n" +"\n" +"Se mesmo assim você deseja sair, por favor utilize\n" +"a opção \"Apenas Sair\"." + +#: gtk_ardour/ardour_ui.cc:1107 +msgid "Save and %1" +msgstr "Salvar e %1" + +#: gtk_ardour/ardour_ui.cc:1112 +msgid "Just %1" +msgstr "Apenas %1" + +#: gtk_ardour/ardour_ui.cc:1117 +msgid "Don't %1" +msgstr "Não %1" + +#: gtk_ardour/ardour_ui.cc:1126 +msgid "session" +msgstr "sessão" + +#: gtk_ardour/ardour_ui.cc:1128 +msgid "snapshot" +msgstr "capturar instantâneo" + +#: gtk_ardour/ardour_ui.cc:1130 +msgid "" +"The %1\n" +"\"%2\"\n" +"has not been saved.\n" +"\n" +"Any changes made this time\n" +"will be lost unless you save it.\n" +"\n" +"What do you want to do?" +msgstr "" +"A \"%1\"\n" +"\"%2\"\n" +"ainda não foi salva.\n" +"\n" +"Qualquer alteração feita até o momento\n" +"será perdida se você não salvar.\n" +"\n" +"O que você quer fazer?" + +#: gtk_ardour/ardour_ui.cc:1151 +msgid "Prompter" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1152 +msgid "ardour: save session?" +msgstr "ardour: salvar sessão?" + +#: gtk_ardour/ardour_ui.cc:1219 +#, c-format +msgid "disconnected" +msgstr "desconectado" + +#: gtk_ardour/ardour_ui.cc:1226 +#, c-format +msgid "SR: %.1f kHz / %4.1f msecs" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1230 +#, c-format +msgid "SR: %u kHz / %4.1f msecs" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1243 +#, c-format +msgid "DSP Load: %.1f%%" +msgstr "DSP Carregada: %.1f%%" + +#: gtk_ardour/ardour_ui.cc:1253 +#, c-format +msgid "Disk r:%5.1f w:%5.1f MB/s" +msgstr "Disco r:%5.1f w:%5.1f MB/s" + +#: gtk_ardour/ardour_ui.cc:1267 +#, c-format +msgid "Buffers p:%%% c:%%%" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1294 +msgid "space: 24hrs+" +msgstr "espaço: 24hrs+" + +#: gtk_ardour/ardour_ui.cc:1324 +#, c-format +msgid "space: %02dh:%02dm:%02ds" +msgstr "espaço: %02dh:%02dm:%02ds" + +#: gtk_ardour/ardour_ui.cc:1575 +msgid "programming error: impossible control method" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1800 +msgid "cancel" +msgstr "cancelar" + +#: gtk_ardour/ardour_ui.cc:1801 +msgid "rescan" +msgstr "rescanear" + +# +#: gtk_ardour/ardour_ui.cc:1842 +msgid "open session" +msgstr "abrir sessão" + +#: gtk_ardour/ardour_ui.cc:1897 +msgid "Patience is a virtue.\n" +msgstr "Paciência é uma virtude.\n" + +#: gtk_ardour/ardour_ui.cc:1906 +msgid "You cannot add a track without a session already loaded." +msgstr "" +"Você não pode adicionar uma trilha se uma sessão não estiver carregada." + +#: gtk_ardour/ardour_ui.cc:1913 +msgid "could not create new audio track" +msgstr "não pôde criar uma nova trilha de áudio" + +#: gtk_ardour/ardour_ui.cc:1917 +msgid "could not create new audio bus" +msgstr "não foi possível criar um novo barramento de áudio" + +#: gtk_ardour/ardour_ui.cc:1936 +msgid "" +"There are insufficient JACK ports available\n" +"to create a new track or bus.\n" +"You should save Ardour, exit and\n" +"restart JACK with more ports." +msgstr "" +"Não existe um número suficiente de portas do JACK disponíveis\n" +"para criar uma nova trilha ou barramento.\n" +"Você deve salvar Ardour, sair e\n" +"reiniciar o JACK com mais portas." + +#: gtk_ardour/ardour_ui.cc:2071 +msgid "" +"Please create 1 or more track\n" +"before trying to record.\n" +"Check the Session menu." +msgstr "" +"Faça favor criar um ou mais trilhas\n" +"antes de tentar gravar.\n" +"Vir o menu de Sessão." + +#: gtk_ardour/ardour_ui.cc:2312 +msgid "" +"JACK has either been shutdown or it\n" +"disconnected Ardour because Ardour\n" +"was not fast enough. You can save the\n" +"session and/or try to reconnect to JACK ." +msgstr "" +"O serviço de audio (JACK) foi terminado ou\n" +"o mesmo desligou a sua conexão com o Ardour,\n" +"talvez porque este não foi rápido o suficiente.\n" +"A sessão corrente deverá ser salva e\n" +"o serviço JACK reiniciado, tal como o Ardour." + +#: gtk_ardour/ardour_ui.cc:2328 +msgid "Unable to create all required ports" +msgstr "Impossível criar todas as portas solicitadas" + +#: gtk_ardour/ardour_ui.cc:2336 +msgid "Unable to start the session running" +msgstr "Impossível iniciar a sessão" + +#: gtk_ardour/ardour_ui.cc:2472 +msgid "No Stream" +msgstr "Sem fluxo" + +#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518 +msgid "none" +msgstr "nenhum" + +#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527 +#: gtk_ardour/automation_time_axis.cc:189 +#: gtk_ardour/automation_time_axis.cc:218 +#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211 +#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947 +#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659 +msgid "off" +msgstr "desligado" + +#: gtk_ardour/ardour_ui.cc:2548 +msgid "Name for snapshot" +msgstr "Nome para a imagem capturada" + +#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294 +msgid "Name for mix template:" +msgstr "Nome para o esquema de mixer" + +#: gtk_ardour/ardour_ui.cc:2717 +msgid "-template" +msgstr "-esquema/template" + +#: gtk_ardour/ardour_ui.cc:2760 +msgid "Session %1 already exists at %2" +msgstr "Sessão %1 ainda existe à %2" + +#: gtk_ardour/ardour_ui.cc:2832 +msgid "" +"You do not have write access to this session.\n" +"This prevents the session from being loaded." +msgstr "" +"Você não tem permissão de escrita nesta sessão\n" +"Isto impede que a sessão seja aberta." + +#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897 +msgid "Session \"%1 (snapshot %2)\" did not load successfully" +msgstr "A sessão \"%1 (instantâneo %2)\" não pôde ser carregada" + +#: gtk_ardour/ardour_ui.cc:2966 +msgid "" +"No audio files were ready for cleanup\n" +"\n" +"If this seems suprising, check for any existing\n" +"snapshots. These may still include regions that\n" +"require some unused files to continue to exist." +msgstr "" +"Não existem arquivos de audio para serem limpos\n" +"Se isto parece estranho, procure por instantâneos existentes.\n" +"Eles podem conter regiões que requeiram a existência\n" +"de arquivos não utlizados." + +#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001 +msgid "files" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003 +msgid "file" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3026 +msgid "ardour: cleanup" +msgstr "ardour: limpar" + +#: gtk_ardour/ardour_ui.cc:3040 +msgid "" +"Cleanup is a destructive operation.\n" +"ALL undo/redo information will be lost if you cleanup.\n" +"Unused audio files will be moved to a \"dead sounds\" location." +msgstr "" +"A limpeza é uma operação destrutiva\n" +"TODAS as informações de desfazer/refazer serão perdidas se\n" +"você continuar. Arquivos de audio não usados serão movidos\n" +"para \"dead sounds\"" + +#: gtk_ardour/ardour_ui.cc:3045 +msgid "Proceed with cleanup" +msgstr "Continuar com a limpeza" + +#: gtk_ardour/ardour_ui.cc:3061 +msgid "CleanupDialog" +msgstr "Limpar" + +#: gtk_ardour/ardour_ui.cc:3062 +msgid "ardour cleanup" +msgstr "ardour limpar" + +#: gtk_ardour/ardour_ui.cc:3063 +msgid "ardour_cleanup" +msgstr "ardour_limpar" + +#: gtk_ardour/ardour_ui.cc:3086 +msgid "cleaned files" +msgstr "arquivos limpos" + +#: gtk_ardour/ardour_ui.cc:3087 +msgid "" +"The following %1 %2 were not in use.\n" +"The next time you flush the wastebasket\n" +"it will release an additional %3 %4bytes\n" +"of disk space" +msgstr "" +"Os seguintes %1 %2 não estão em uso.\n" +"Na próxima vez limpe sua lixeira\n" +"isto vai liberar %3 %4bytes\n" +"de espaço no disco rígido" + +#: gtk_ardour/ardour_ui.cc:3110 +msgid "deleted file" +msgstr "arquivo removido" + +#: gtk_ardour/ardour_ui.cc:3111 +msgid "" +"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space" +msgstr "" +"Os seguintes %1 arquivo%2 foram deletados, liberando %3 %4bytes de espaço no " +"disco rígido" + +#: gtk_ardour/ardour_ui.cc:3226 +msgid "Recording was stopped because your system could not keep up." +msgstr "A gravação foi encerrada porque seu sistema não consegue acompanhar" + +#: gtk_ardour/ardour_ui.cc:3248 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to write data to disk\n" +"quickly enough to keep up with recording.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3266 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to read data from disk\n" +"quickly enough to keep up with playback.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3291 +msgid "Recover from crash" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3292 +msgid "Ignore crash data" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3293 +msgid "" +"This session appears to have been in\n" +"middle of recording when ardour or\n" +"the computer was shutdown.\n" +"\n" +"Ardour can recover any captured audio for\n" +"you, or it can ignore it. Please decide\n" +"what you would like to do.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3338 +msgid "Could not disconnect from JACK" +msgstr "Não foi possível se desconectar ao servidor JACK" + +#: gtk_ardour/ardour_ui.cc:3351 +#, fuzzy +msgid "Could not reconnect to JACK" +msgstr "Não foi possível se conectar ao servidor JACK" + +#: gtk_ardour/ardour_ui2.cc:60 +msgid "UI: cannot setup editor" +msgstr "não foi possível iniciar o editor" + +#: gtk_ardour/ardour_ui2.cc:65 +msgid "UI: cannot setup mixer" +msgstr "não foi possível iniciar o mixer" + +#: gtk_ardour/ardour_ui2.cc:70 +msgid "UI: cannot setup meter_bridge" +msgstr "não foi possível iniciar o medidor volumétrico (VU)" + +#: gtk_ardour/ardour_ui2.cc:98 +msgid "MMC + Local" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:99 +msgid "MMC" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:100 +msgid "Local" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:117 +msgid "MMC ID" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:215 +msgid "Play from playhead" +msgstr "Reproduzir a partir do início" + +#: gtk_ardour/ardour_ui2.cc:216 +msgid "Stop playback" +msgstr "Parar reprodução" + +#: gtk_ardour/ardour_ui2.cc:217 +msgid "Play range/selection" +msgstr "Reproduzir intervalo/seleção" + +#: gtk_ardour/ardour_ui2.cc:218 +msgid "Go to start of session" +msgstr "Ir para o início da sessão" + +#: gtk_ardour/ardour_ui2.cc:219 +msgid "Go to end of session" +msgstr "Ir para o fim da sessão" + +#: gtk_ardour/ardour_ui2.cc:220 +msgid "Play loop range" +msgstr "Reproduzir intervalo" + +#: gtk_ardour/ardour_ui2.cc:221 +msgid "Return to last playback start when stopped" +msgstr "Ir para o início da última reprodução quando parar" + +#: gtk_ardour/ardour_ui2.cc:222 +msgid "Start playback after any locate" +msgstr "Iniciar reprodução após qualquer localização" + +#: gtk_ardour/ardour_ui2.cc:223 +msgid "Be sensible about input monitoring" +msgstr "Sensível à monitoração na entrada" + +#: gtk_ardour/ardour_ui2.cc:224 +msgid "Start recording at auto-punch start" +msgstr "Iniciar gravação no início do ponto-automático" + +#: gtk_ardour/ardour_ui2.cc:225 +msgid "Stop recording at auto-punch end" +msgstr "Parar gravação no final do ponto-automático" + +#: gtk_ardour/ardour_ui2.cc:226 +msgid "Enable/Disable audio click" +msgstr "Habilitar/desabilitar metrônomo" + +#: gtk_ardour/ardour_ui2.cc:227 +msgid "Enable/Disable follow playhead" +msgstr "Habilitar/desbilitar reprodução contínua" + +#: gtk_ardour/ardour_ui2.cc:228 +msgid "Shuttle speed control" +msgstr "Velocidade do controle" + +#: gtk_ardour/ardour_ui2.cc:229 +#, c-format +msgid "Select semitones or %%-age for speed display" +msgstr "Selecionar semitons ou percentual para a velocidade da tela" + +#: gtk_ardour/ardour_ui2.cc:230 +msgid "Select sprung or wheel behaviour" +msgstr "Selecionar ajuste fixo ou retornável" + +#: gtk_ardour/ardour_ui2.cc:231 +msgid "Current transport speed" +msgstr "Velocidade atual do transporte" + +#: gtk_ardour/ardour_ui2.cc:312 +msgid "Primary clock" +msgstr "Relógio primeiramente" + +#: gtk_ardour/ardour_ui2.cc:313 +msgid "secondary clock" +msgstr "Relógio secundário" + +#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751 +#: gtk_ardour/ardour_ui2.cc:770 +msgid "stopped" +msgstr "parado" + +#: gtk_ardour/ardour_ui2.cc:431 +msgid "ardour: clock" +msgstr "ardour: relógio" + +#: gtk_ardour/ardour_ui2.cc:721 +msgid "st" +msgstr "o." + +#: gtk_ardour/ardour_ui2.cc:731 +msgid "sprung" +msgstr "retornável" + +#: gtk_ardour/ardour_ui2.cc:742 +msgid "wheel" +msgstr "fixo" + +#: gtk_ardour/ardour_ui_dependents.cc:74 +msgid "keyboard_target: error setting binding state: invalid node" +msgstr "" + +#: gtk_ardour/ardour_ui_dialogs.cc:158 +msgid "close session" +msgstr "fechar sessão" + +#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895 +msgid "New" +msgstr "Novo" + +#: gtk_ardour/ardour_ui_ed.cc:76 +msgid "Open" +msgstr "Abrir" + +#: gtk_ardour/ardour_ui_ed.cc:77 +msgid "Recent" +msgstr "Recente" + +#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +msgid "Close" +msgstr "Fechar" + +#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488 +msgid "Add Track/Bus" +msgstr "Adicionar Trilha/Barramento" + +#: gtk_ardour/ardour_ui_ed.cc:99 +msgid "Connect" +msgstr "Conectar" + +#: gtk_ardour/ardour_ui_ed.cc:100 +msgid "Image Compositor" +msgstr "Compositor de imagem" + +#: gtk_ardour/ardour_ui_ed.cc:114 +msgid "Save" +msgstr "Salvar" + +#: gtk_ardour/ardour_ui_ed.cc:118 +msgid "Snapshot" +msgstr "Capturar instantâneo" + +#: gtk_ardour/ardour_ui_ed.cc:126 +msgid "Save Template..." +msgstr "Salvar Esquema..." + +#: gtk_ardour/ardour_ui_ed.cc:133 +msgid "Export session to audiofile..." +msgstr "Exportar sessão para arquivo de áudio" + +#: gtk_ardour/ardour_ui_ed.cc:134 +msgid "Export range to audiofile..." +msgstr "Exportar intervalo para arquivo de áudio" + +#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312 +#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118 +#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227 +msgid "Export" +msgstr "Exportar" + +#: gtk_ardour/ardour_ui_ed.cc:146 +msgid "Cleanup unused sources" +msgstr "Limpar fontes não usadas" + +#: gtk_ardour/ardour_ui_ed.cc:147 +msgid "Flush wastebasket" +msgstr "Esvaziar lixeira" + +#: gtk_ardour/ardour_ui_ed.cc:149 +msgid "Cleanup" +msgstr "Limpar" + +#: gtk_ardour/ardour_ui_ed.cc:154 +msgid "Quit" +msgstr "Sair" + +#: gtk_ardour/ardour_ui_ed.cc:156 +msgid "Session" +msgstr "Sessão" + +#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287 +#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499 +#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570 +#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412 +msgid "Edit" +msgstr "Editar" + +#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572 +#: gtk_ardour/mixer_strip.cc:631 +msgid "Disconnect" +msgstr "Desconectar" + +#: gtk_ardour/ardour_ui_ed.cc:174 +#, fuzzy +msgid "Reconnect" +msgstr "Conectar" + +#: gtk_ardour/ardour_ui_ed.cc:192 +msgid "Latency" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:195 +msgid "JACK" +msgstr "JACK" + +#: gtk_ardour/ardour_ui_ed.cc:205 +msgid "Editor" +msgstr "Editor" + +#: gtk_ardour/ardour_ui_ed.cc:206 +msgid "Mixer" +msgstr "Mixer" + +#: gtk_ardour/ardour_ui_ed.cc:212 +msgid "Options Editor" +msgstr "Preferências" + +#: gtk_ardour/ardour_ui_ed.cc:219 +msgid "Audio Library" +msgstr "Biblioteca de Ãudio" + +#: gtk_ardour/ardour_ui_ed.cc:225 +msgid "Track/Bus Inspector" +msgstr "Inspetador de Trilhas/Barramentos" + +#: gtk_ardour/ardour_ui_ed.cc:232 +msgid "Connections" +msgstr "Conexões" + +#: gtk_ardour/ardour_ui_ed.cc:240 +msgid "Meter Bridge" +msgstr "VU (medidor volumétrico)" + +#: gtk_ardour/ardour_ui_ed.cc:248 +msgid "Locations" +msgstr "Localizações" + +#: gtk_ardour/ardour_ui_ed.cc:255 +msgid "Big Clock" +msgstr "Metrônomo" + +#: gtk_ardour/ardour_ui_ed.cc:261 +msgid "About" +msgstr "Sobre" + +#: gtk_ardour/ardour_ui_ed.cc:264 +msgid "Windows" +msgstr "Janelas" + +#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203 +msgid "SMPTE" +msgstr "" + +#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202 +#: gtk_ardour/editor_rulers.cc:359 +msgid "Bars:Beats" +msgstr "Compassos:Batimentos" + +#: gtk_ardour/audio_clock.cc:1642 +msgid "Minutes:Seconds" +msgstr "Minutos:Segundos" + +#: gtk_ardour/audio_clock.cc:1643 +msgid "Audio Frames" +msgstr "Quadros de Ãudio" + +#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356 +#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713 +#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774 +#: gtk_ardour/option_editor.cc:794 +msgid "Off" +msgstr "Desligar" + +#: gtk_ardour/audio_clock.cc:1646 +msgid "Mode" +msgstr "Modo" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523 +msgid "m" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524 +msgid "s" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:104 +msgid "r" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:108 +msgid "g" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:109 +msgid "p" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44 +#: gtk_ardour/visual_time_axis.cc:90 +msgid "h" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:111 +msgid "a" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89 +msgid "v" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:185 +msgid "Record" +msgstr "Gravar" + +#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191 +msgid "Solo" +msgstr "Solo" + +#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236 +#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433 +msgid "Mute" +msgstr "Mutar" + +#: gtk_ardour/audio_time_axis.cc:188 +msgid "Edit Group" +msgstr "Editar Grupo" + +#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110 +msgid "Display Height" +msgstr "Altura" + +#: gtk_ardour/audio_time_axis.cc:190 +msgid "Playlist" +msgstr "Lista de reprodução" + +#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752 +msgid "Automation" +msgstr "Automação" + +#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111 +msgid "Visual options" +msgstr "Opções de aparência" + +#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112 +msgid "Hide this track" +msgstr "Ocultar esta trilha" + +#: gtk_ardour/audio_time_axis.cc:349 +msgid "No group" +msgstr "Sem grupo" + +#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447 +#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229 +msgid "Height" +msgstr "Altura" + +#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266 +#: gtk_ardour/marker_time_axis.cc:230 +msgid "Color" +msgstr "Cor" + +#: gtk_ardour/audio_time_axis.cc:720 +msgid "Hide all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:721 +msgid "Show all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:729 +msgid "show all automation" +msgstr "mostra toda a automação" + +#: gtk_ardour/audio_time_axis.cc:732 +msgid "show existing automation" +msgstr "mostra a automação existente" + +#: gtk_ardour/audio_time_axis.cc:735 +msgid "hide all automation" +msgstr "ocultar toda a automação" + +#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204 +#: gtk_ardour/editor.cc:234 +msgid "gain" +msgstr "ganho" + +#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244 +msgid "pan" +msgstr "pan" + +#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388 +msgid "Plugins" +msgstr "Entradas" + +#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95 +msgid "Show waveforms" +msgstr "Mostrar formas de onda áudio" + +#: gtk_ardour/audio_time_axis.cc:766 +msgid "Traditional" +msgstr "Tradicional" + +#: gtk_ardour/audio_time_axis.cc:769 +msgid "Rectified" +msgstr "Corrigido" + +#: gtk_ardour/audio_time_axis.cc:772 +msgid "Waveform" +msgstr "Forma de onda" + +#: gtk_ardour/audio_time_axis.cc:782 +#, fuzzy +msgid "align with existing material" +msgstr "Material existente" + +#: gtk_ardour/audio_time_axis.cc:787 +#, fuzzy +msgid "align with capture time" +msgstr "Tempo de captura" + +#: gtk_ardour/audio_time_axis.cc:793 +#, fuzzy +msgid "Alignment" +msgstr "Alinhamento" + +#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288 +msgid "Active" +msgstr "Ativar" + +#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386 +#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467 +#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269 +#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233 +#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83 +msgid "Remove" +msgstr "Remover" + +#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880 +#: gtk_ardour/audio_time_axis.cc:911 +msgid "Name for playlist" +msgstr "Nome para a lista de reprodução" + +#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433 +msgid "a track already exists with that name" +msgstr "já existe uma trilha com este nome" + +#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001 +#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539 +msgid "programming error: " +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:1889 +msgid "Current: %1" +msgstr "Atual: %1" + +#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452 +#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226 +#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377 +msgid "Rename" +msgstr "Renomear" + +#: gtk_ardour/audio_time_axis.cc:1896 +msgid "New Copy" +msgstr "Nova Cópia" + +#: gtk_ardour/audio_time_axis.cc:1898 +msgid "Clear Current" +msgstr "Limpar Atual" + +#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472 +#: gtk_ardour/editor.cc:2557 +msgid "Select" +msgstr "Selecionar" + +#: gtk_ardour/automation_line.cc:904 +msgid "automation event move" +msgstr "mover evento de automação" + +#: gtk_ardour/automation_line.cc:906 +msgid "automation range drag" +msgstr "arrastar intervalo de automação" + +#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64 +msgid "remove control point" +msgstr "Remover ponto de controlo" + +#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010 +msgid "clear" +msgstr "limpar" + +#: gtk_ardour/automation_time_axis.cc:80 +msgid "track height" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:81 +msgid "automation state" +msgstr "estado do automação" + +#: gtk_ardour/automation_time_axis.cc:82 +msgid "clear track" +msgstr "limpar trilha" + +#: gtk_ardour/automation_time_axis.cc:83 +msgid "hide track" +msgstr "ocultar esta trilha" + +#: gtk_ardour/automation_time_axis.cc:191 +#: gtk_ardour/automation_time_axis.cc:229 +#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213 +#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419 +#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50 +msgid "play" +msgstr "reproduzir" + +#: gtk_ardour/automation_time_axis.cc:193 +#: gtk_ardour/automation_time_axis.cc:240 +#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215 +#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422 +#: gtk_ardour/plugin_ui.cc:663 +msgid "write" +msgstr "escrever" + +#: gtk_ardour/automation_time_axis.cc:195 +#: gtk_ardour/automation_time_axis.cc:251 +#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217 +#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953 +#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665 +msgid "touch" +msgstr "marca como novo" + +#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274 +#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428 +msgid "???" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:276 +msgid "clear automation" +msgstr "limpar automação" + +#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453 +#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398 +msgid "Hide" +msgstr "Ocultar" + +#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52 +#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364 +msgid "Clear" +msgstr "Limpar" + +#: gtk_ardour/automation_time_axis.cc:474 +msgid "State" +msgstr "Estado" + +#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49 +msgid "Input Connections" +msgstr "Conexões de entrada" + +#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48 +msgid "Output Connections" +msgstr "Conexões de saída" + +#: gtk_ardour/connection_editor.cc:49 +msgid "New Input" +msgstr "Nova entrada" + +#: gtk_ardour/connection_editor.cc:50 +msgid "New Output" +msgstr "Nova saída" + +#: gtk_ardour/connection_editor.cc:51 +msgid "Delete" +msgstr "Apagar" + +#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96 +msgid "Add Port" +msgstr "Adicionar Porta" + +#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105 +#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786 +msgid "Rescan" +msgstr "Rescanear" + +#: gtk_ardour/connection_editor.cc:101 +msgid "Available Ports" +msgstr "Portas disponíveis" + +#: gtk_ardour/connection_editor.cc:183 +msgid "ardour: connections" +msgstr "ardour: conexões" + +#: gtk_ardour/connection_editor.cc:513 +#, c-format +msgid "in %d" +msgstr "em %d" + +#: gtk_ardour/connection_editor.cc:644 +msgid "Name for new connection:" +msgstr "Nome para a nova conexão:" + +#: gtk_ardour/crossfade_edit.cc:71 +#, fuzzy +msgid "crossfade editor" +msgstr "fade in na edição" + +#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449 +msgid "Reset" +msgstr "Reiniciar" + +#: gtk_ardour/crossfade_edit.cc:78 +msgid "Fade" +msgstr "Fade" + +#: gtk_ardour/crossfade_edit.cc:79 +msgid "Out (dry)" +msgstr "Saída (flat)" + +#: gtk_ardour/crossfade_edit.cc:80 +msgid "Out" +msgstr "Saídas" + +#: gtk_ardour/crossfade_edit.cc:81 +msgid "In (dry)" +msgstr "Entrada (flat)" + +#: gtk_ardour/crossfade_edit.cc:82 +msgid "In" +msgstr "Entrada" + +#: gtk_ardour/crossfade_edit.cc:84 +msgid "With Pre-roll" +msgstr "Com pré-rolagem" + +#: gtk_ardour/crossfade_edit.cc:85 +msgid "With Post-roll" +msgstr "Com pós-rolagem" + +#: gtk_ardour/crossfade_edit.cc:93 +msgid "Fade In" +msgstr "Fade In" + +#: gtk_ardour/crossfade_edit.cc:94 +msgid "Fade Out" +msgstr "Fade Out" + +#: gtk_ardour/crossfade_edit.cc:98 +msgid "ardour: x-fade edit" +msgstr "ardour: editar cross fade" + +#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311 +#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189 +msgid "Audition" +msgstr "Audição" + +#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804 +msgid "Regions/name" +msgstr "Regiões/nome" + +#: gtk_ardour/editor.cc:108 +msgid "Chunks" +msgstr "Trechos" + +#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079 +msgid "Slide" +msgstr "Deslizar" + +#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077 +msgid "Splice" +msgstr "Reunir" + +#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136 +#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96 +#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977 +msgid "None" +msgstr "Nenhum" + +#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124 +msgid "CD Frames" +msgstr "Quadros de CD" + +#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126 +msgid "SMPTE Frames" +msgstr "SMPTE Frames" + +#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128 +msgid "SMPTE Seconds" +msgstr "SMPTE segundo" + +#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130 +msgid "SMPTE Minutes" +msgstr "SMPTE Minutos" + +#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132 +msgid "Seconds" +msgstr "Segundos" + +#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134 +msgid "Minutes" +msgstr "Minutos" + +# ## msgstr "Saídas Principais" +#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106 +msgid "Beats/32" +msgstr "Batimentos/32" + +#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104 +msgid "Beats/16" +msgstr "Batimentos/16" + +#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102 +msgid "Beats/8" +msgstr "Batimentos/8" + +#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100 +msgid "Beats/4" +msgstr "Batimentos/4" + +#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098 +msgid "Beats/3" +msgstr "Batimentos/3" + +#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108 +msgid "Beats" +msgstr "Batimentos" + +#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110 +msgid "Bars" +msgstr "Compassos" + +#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112 +msgid "Marks" +msgstr "Marcas" + +#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114 +#: gtk_ardour/editor.cc:4182 +msgid "Edit Cursor" +msgstr "Cursor de Edição" + +#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116 +msgid "Region starts" +msgstr "Começo de regiões" + +#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118 +msgid "Region ends" +msgstr "Fim de regiões" + +#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122 +msgid "Region syncs" +msgstr "Sincronizações de região" + +#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120 +msgid "Region bounds" +msgstr "Divisas de região" + +#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153 +#: gtk_ardour/time_axis_view.cc:449 +msgid "Normal" +msgstr "Normal" + +#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155 +msgid "Magnetic" +msgstr "Magnético" + +#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174 +#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237 +msgid "Left" +msgstr "Esquerdo" + +#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176 +#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238 +msgid "Right" +msgstr "Direito" + +#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178 +msgid "Center" +msgstr "Centro" + +#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180 +msgid "Playhead" +msgstr "Início" + +#: gtk_ardour/editor.cc:201 +msgid "Mins:Secs" +msgstr "Mins:Segs" + +#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353 +msgid "Frames" +msgstr "Quadros" + +#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373 +msgid "Tempo" +msgstr "Tempo" + +#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367 +msgid "Meter" +msgstr "VU (medidor volumétrico)" + +#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379 +msgid "Location Markers" +msgstr "Marcas de Localização" + +#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385 +msgid "Range Markers" +msgstr "Marcas de Intervalos" + +#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391 +msgid "Loop/Punch Ranges" +msgstr "Intervalos Loop/Insersão" + +#: gtk_ardour/editor.cc:221 +msgid "" +"editor\n" +"mixer" +msgstr "" + +#: gtk_ardour/editor.cc:232 +msgid "range" +msgstr "intervalo" + +#: gtk_ardour/editor.cc:233 +msgid "object" +msgstr "objeto" + +#: gtk_ardour/editor.cc:235 +msgid "zoom" +msgstr "zoom" + +#: gtk_ardour/editor.cc:236 +msgid "timefx" +msgstr "" + +#: gtk_ardour/editor.cc:237 +msgid "listen" +msgstr "" + +#: gtk_ardour/editor.cc:239 +msgid "mode" +msgstr "modo" + +#: gtk_ardour/editor.cc:240 +msgid "automation" +msgstr "automação" + +#: gtk_ardour/editor.cc:242 +msgid "Edit Mode" +msgstr "Modo de edição" + +#: gtk_ardour/editor.cc:243 +msgid "Snap To" +msgstr "Ajustar a" + +#: gtk_ardour/editor.cc:244 +msgid "Snap Mode" +msgstr "Modo de Ajuste" + +#: gtk_ardour/editor.cc:245 +msgid "Zoom Focus" +msgstr "Foco de Zoom" + +#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364 +#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579 +msgid "Nudge" +msgstr "Retocar" + +#: gtk_ardour/editor.cc:511 +msgid "Zoom in" +msgstr "Mais Zoom" + +#: gtk_ardour/editor.cc:512 +msgid "Zoom out" +msgstr "Menos Zoom" + +#: gtk_ardour/editor.cc:517 +msgid "Zoom to session" +msgstr "Zoom na sessão" + +#: gtk_ardour/editor.cc:536 +msgid "Zoom Span" +msgstr "Alcance de zoom" + +#: gtk_ardour/editor.cc:566 +msgid "Edit Groups" +msgstr "Editar Grupos" + +#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142 +msgid "-all-" +msgstr "-tudo-" + +#: gtk_ardour/editor.cc:718 +msgid "Nudge region/selection forwards" +msgstr "Avançar o mínimo região/seleção" + +#: gtk_ardour/editor.cc:719 +msgid "Nudge region/selection backwards" +msgstr "Voltar o mínimo região/seleção" + +#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308 +msgid "ardour: editor" +msgstr "" + +#: gtk_ardour/editor.cc:729 +msgid "ardour_editor" +msgstr "" + +#: gtk_ardour/editor.cc:846 +msgid "VerboseCanvasCursor" +msgstr "" + +#: gtk_ardour/editor.cc:1405 +msgid "FirstActionMessage" +msgstr "" + +#: gtk_ardour/editor.cc:1407 +msgid "Start a new session\n" +msgstr "Iniciar uma nova sessão\n" + +#: gtk_ardour/editor.cc:1408 +msgid "via Session menu" +msgstr "via menu de Sessão" + +#: gtk_ardour/editor.cc:1703 +msgid "ardour: editor: " +msgstr "" + +#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796 +#: gtk_ardour/editor_markers.cc:797 +msgid "Loop" +msgstr "Ciclo" + +#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810 +#: gtk_ardour/editor_markers.cc:823 +msgid "Punch" +msgstr "Inserção" + +#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688 +msgid "programming error: fade in canvas item has no regionview data pointer!" +msgstr "" + +#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986 +#: gtk_ardour/redirect_box.cc:401 +msgid "Deactivate" +msgstr "Desativar" + +#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988 +#: gtk_ardour/redirect_box.cc:398 +msgid "Activate" +msgstr "Ativar" + +#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993 +msgid "Linear" +msgstr "Linear" + +#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994 +#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734 +#: gtk_ardour/option_editor.cc:796 +msgid "Slowest" +msgstr "Menor" + +#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995 +#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735 +#: gtk_ardour/option_editor.cc:798 +msgid "Slow" +msgstr "Devegar" + +#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996 +#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737 +#: gtk_ardour/option_editor.cc:802 +msgid "Fast" +msgstr "Rapido" + +#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997 +#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739 +#: gtk_ardour/option_editor.cc:806 +msgid "Fastest" +msgstr "Rapidamente" + +#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113 +msgid "Freeze" +msgstr "Congelar" + +#: gtk_ardour/editor.cc:2109 +msgid "Unfreeze" +msgstr "Descongelar" + +#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328 +msgid "Unmute" +msgstr "Desmudo" + +#: gtk_ardour/editor.cc:2247 +msgid "Convert to short" +msgstr "" + +#: gtk_ardour/editor.cc:2249 +msgid "Convert to full" +msgstr "" + +#: gtk_ardour/editor.cc:2260 +msgid "Crossfade" +msgstr "Fade cruzado" + +#: gtk_ardour/editor.cc:2303 +msgid "Popup region editor" +msgstr "Editor de região" + +#: gtk_ardour/editor.cc:2304 +msgid "Raise to top layer" +msgstr "Trazer região para frente, primeira camada" + +#: gtk_ardour/editor.cc:2305 +msgid "Lower to bottom layer" +msgstr "Enviar região para a trás, última camada" + +#: gtk_ardour/editor.cc:2307 +msgid "Define sync point" +msgstr "Definir ponto de sincronia" + +#: gtk_ardour/editor.cc:2308 +msgid "Remove sync point" +msgstr "Remover ponto de sincronia" + +#: gtk_ardour/editor.cc:2313 +msgid "Bounce" +msgstr "" + +#: gtk_ardour/editor.cc:2323 +msgid "Lock" +msgstr "Trancar" + +#: gtk_ardour/editor.cc:2324 +msgid "Unlock" +msgstr "Destrancar" + +#: gtk_ardour/editor.cc:2334 +msgid "Original position" +msgstr "Posição original" + +#: gtk_ardour/editor.cc:2340 +msgid "Toggle envelope visibility" +msgstr "" + +#: gtk_ardour/editor.cc:2341 +#, fuzzy +msgid "Toggle envelope active" +msgstr "ativo" + +#: gtk_ardour/editor.cc:2345 +msgid "DeNormalize" +msgstr "Desnormalizar" + +#: gtk_ardour/editor.cc:2347 +msgid "Normalize" +msgstr "Normalizar" + +#: gtk_ardour/editor.cc:2350 +msgid "Reverse" +msgstr "Inverter horizontalmente" + +#: gtk_ardour/editor.cc:2359 +#, fuzzy +msgid "Nudge fwd" +msgstr "Retocar" + +#: gtk_ardour/editor.cc:2360 +#, fuzzy +msgid "Nudge bwd" +msgstr "Retocar" + +#: gtk_ardour/editor.cc:2361 +msgid "Nudge fwd by capture offset" +msgstr "" + +#: gtk_ardour/editor.cc:2362 +msgid "Nudge bwd by capture offset" +msgstr "" + +#: gtk_ardour/editor.cc:2371 +msgid "Start to edit cursor" +msgstr "Do início ao cursor de edição" + +#: gtk_ardour/editor.cc:2372 +msgid "Edit cursor to end" +msgstr "Do cursor de edição ao final" + +#: gtk_ardour/editor.cc:2374 +msgid "Trim" +msgstr "Cortar" + +#: gtk_ardour/editor.cc:2377 +msgid "Split" +msgstr "Separar" + +#: gtk_ardour/editor.cc:2380 +msgid "Make mono regions" +msgstr "Criar regiões mono" + +#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428 +msgid "Duplicate" +msgstr "Duplicar" + +#: gtk_ardour/editor.cc:2384 +msgid "Fill Track" +msgstr "Preencher Trilha" + +#: gtk_ardour/editor.cc:2388 +msgid "Destroy" +msgstr "Remover definitavente" + +#: gtk_ardour/editor.cc:2418 +msgid "Play range" +msgstr "Reproduzir intervalo" + +#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446 +msgid "Loop range" +msgstr "Loop no intervalo" + +#: gtk_ardour/editor.cc:2421 +msgid "Create chunk from range" +msgstr "Criar trecho a partir da intervalo" + +#: gtk_ardour/editor.cc:2423 +msgid "Create Region" +msgstr "Criar Região" + +#: gtk_ardour/editor.cc:2424 +msgid "Separate Region" +msgstr "Separar Região" + +#: gtk_ardour/editor.cc:2425 +msgid "Crop Region to range" +msgstr "Cortar região pela intervalo" + +#: gtk_ardour/editor.cc:2426 +#, fuzzy +msgid "Bounce range" +msgstr "região" + +#: gtk_ardour/editor.cc:2432 +msgid "Fill range w/Region" +msgstr "Preencher intervalo com região" + +#: gtk_ardour/editor.cc:2434 +msgid "Range" +msgstr "Intervalo" + +#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538 +msgid "Play from edit cursor" +msgstr "Reproduzir a partir do cursor" + +#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539 +msgid "Play from start" +msgstr "Reproduzir do início" + +#: gtk_ardour/editor.cc:2451 +msgid "Play region" +msgstr "Reproduzir região" + +#: gtk_ardour/editor.cc:2453 +msgid "Loop Region" +msgstr "Região de loop" + +#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540 +#: gtk_ardour/library_ui.cc:972 +msgid "Play" +msgstr "Reproduzir" + +#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548 +msgid "Select All in track" +msgstr "Selecionar tudo na trilha" + +#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549 +msgid "Select All" +msgstr "Selecionar Tudo" + +#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550 +msgid "Invert in track" +msgstr "Inverter verticalmente na trilha" + +#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551 +msgid "Invert" +msgstr "Inverter verticalmente" + +#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553 +msgid "Select loop range" +msgstr "Selecionar intervalo de loop" + +#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554 +msgid "Select punch range" +msgstr "Selecionar intervalo de inserção" + +#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565 +#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369 +msgid "Cut" +msgstr "Cortar" + +#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566 +#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371 +msgid "Copy" +msgstr "Copiar" + +#: gtk_ardour/editor.cc:2482 +msgid "Paste at edit cursor" +msgstr "Colar à cursor de edição" + +#: gtk_ardour/editor.cc:2483 +msgid "Paste at mouse" +msgstr "Colar à mouse" + +#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923 +msgid "Align" +msgstr "Alinhamento" + +#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925 +msgid "Align Relative" +msgstr "Alinhamento Relativo" + +#: gtk_ardour/editor.cc:2492 +msgid "Insert chunk" +msgstr "Inserir trecho" + +#: gtk_ardour/editor.cc:2496 +msgid "New Region from range" +msgstr "Nova região a partir da intervalo" + +#: gtk_ardour/editor.cc:2497 +msgid "Separate Range" +msgstr "Separar intervalo" + +#: gtk_ardour/editor.cc:2507 +msgid "Insert Region" +msgstr "Inserir região" + +#: gtk_ardour/editor.cc:2508 +msgid "Insert external sndfile" +msgstr "Inserir arquivo de áudio externo" + +#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438 +msgid "Import" +msgstr "Importar" + +#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574 +msgid "Nudge entire track fwd" +msgstr "Retorcar toda a trilha para frente" + +#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575 +msgid "Nudge track after edit cursor fwd" +msgstr "Retocar trilha após o cursor de edição" + +#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576 +msgid "Nudge entire track bwd" +msgstr "Retorcar toda a trilha para trás" + +#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577 +msgid "Nudge track after edit cursor bwd" +msgstr "Retocar toda a trilha, do cursor de edição para trás" + +#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920 +#: gtk_ardour/redirect_box.cc:373 +msgid "Paste" +msgstr "Colar" + +#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645 +#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799 +msgid "add marker" +msgstr "adicionar marca" + +#: gtk_ardour/editor.cc:3084 +msgid "select/move objects" +msgstr "selecionar/mover objetos" + +#: gtk_ardour/editor.cc:3085 +msgid "select/move ranges" +msgstr "selecionar/mover intervalos" + +#: gtk_ardour/editor.cc:3086 +msgid "draw gain automation" +msgstr "desenhar ganho automático" + +#: gtk_ardour/editor.cc:3087 +msgid "select zoom range" +msgstr "selecionar intervalo de zoom" + +#: gtk_ardour/editor.cc:3088 +msgid "stretch/shrink regions" +msgstr "esticar/encolher regiões" + +#: gtk_ardour/editor.cc:3089 +#, fuzzy +msgid "listen to specific regions" +msgstr "Ouça no região especifica" + +#: gtk_ardour/editor.cc:3213 +msgid "Start:" +msgstr "Inicio:" + +#: gtk_ardour/editor.cc:3214 +msgid "End:" +msgstr "Final:" + +#: gtk_ardour/editor.cc:3215 +msgid "Edit:" +msgstr "Editar:" + +#: gtk_ardour/editor.cc:3429 +msgid "incorrectly formatted URI list, ignored" +msgstr "" + +#: gtk_ardour/editor.cc:3611 +#, fuzzy +msgid "set selected trackview" +msgstr "Inserir seleção" + +#: gtk_ardour/editor.cc:3647 +#, fuzzy +msgid "set selected control point" +msgstr "Remover ponto de controlo" + +#: gtk_ardour/editor.cc:3719 +#, fuzzy +msgid "set selected regionview" +msgstr "Loop região selecionada" + +#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835 +#, fuzzy +msgid "set selected regions" +msgstr "Loop região selecionada" + +#: gtk_ardour/editor.cc:3891 +msgid "Undo" +msgstr "Desfazer" + +#: gtk_ardour/editor.cc:3893 +msgid "Undo (%1)" +msgstr "Desfazer (%1)" + +#: gtk_ardour/editor.cc:3903 +msgid "Redo" +msgstr "Refazer" + +#: gtk_ardour/editor.cc:3905 +msgid "Redo (%1)" +msgstr "Refazer (%1)" + +#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946 +msgid "... as new track" +msgstr "" + +#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947 +#, fuzzy +msgid "... as new region" +msgstr "normalizar região" + +#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452 +msgid "Import audio (copy)" +msgstr "Importar áudio (copiar)" + +#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457 +msgid "Embed audio (link)" +msgstr "Encaixar áudio (link)" + +#: gtk_ardour/editor.cc:3953 +msgid "Remove last capture" +msgstr "Remover última captura" + +#: gtk_ardour/editor.cc:3974 +msgid "Duplicate how many times?" +msgstr "Duplicar quantas vezes?" + +#: gtk_ardour/editor.cc:4550 +msgid "" +"Playlist %1 is currently unused.\n" +"If left alone, no audio files used by it will be cleaned.\n" +"If deleted, audio files used by it alone by will cleaned." +msgstr "" + +#: gtk_ardour/editor.cc:4555 +#, fuzzy +msgid "Delete playlist" +msgstr "Nome para a imagem capturada" + +#: gtk_ardour/editor.cc:4556 +#, fuzzy +msgid "Keep playlist" +msgstr "Nome para a imagem capturada" + +#: gtk_ardour/editor.cc:4557 +#, fuzzy +msgid "Cancel cleanup" +msgstr "Limpar" + +#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258 +#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290 +msgid "" +"programming error: control point canvas item has no control point object " +"pointer!" +msgstr "" + +#: gtk_ardour/editor_canvas_events.cc:717 +msgid "programming error: line canvas item has no line object pointer!" +msgstr "" + +#: gtk_ardour/editor_canvas_events.cc:744 +#: gtk_ardour/editor_canvas_events.cc:784 +#: gtk_ardour/editor_canvas_events.cc:823 +msgid "programming error: no \"rect\" pointer associated with selection item" +msgstr "" + +#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298 +#: gtk_ardour/mixer_ui.cc:670 +msgid "Show All" +msgstr "Mostrar Tudo" + +#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299 +#: gtk_ardour/mixer_ui.cc:671 +msgid "Hide All" +msgstr "Ocultar Tudo" + +#: gtk_ardour/editor_edit_groups.cc:98 +msgid "Name for new edit group" +msgstr "Nome para o novo grupo de edição" + +#: gtk_ardour/editor_export_audio.cc:60 +msgid "" +"There is no range to export.\n" +"\n" +"Select a range using the range mouse mode" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707 +msgid "programming error: no ImageFrameView selected" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930 +msgid "programming error: no MarkerView selected" +msgstr "" + +#: gtk_ardour/editor_keys.cc:187 +#, fuzzy +msgid "keyboard selection" +msgstr "Separar Seleção" + +#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376 +#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526 +#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584 +#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650 +#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700 +#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960 +#: gtk_ardour/editor_mouse.cc:4075 +msgid "programming error: marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681 +msgid "remove marker" +msgstr "remover marca" + +#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494 +msgid "Locate to" +msgstr "Ir para" + +#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495 +msgid "Play from" +msgstr "Reproduzir de" + +#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496 +msgid "Set from playhead" +msgstr "Marcar aqui" + +#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497 +#, fuzzy +msgid "Set from range" +msgstr "Marcar um intervalo de loop" + +#: gtk_ardour/editor_markers.cc:479 +msgid "Set Loop Range" +msgstr "Marcar um intervalo de loop" + +#: gtk_ardour/editor_markers.cc:480 +msgid "Set Punch Range" +msgstr "Fazer intervalo de inserção" + +#: gtk_ardour/editor_markers.cc:736 +msgid "ardour: rename mark" +msgstr "ardour: renomear marca" + +#: gtk_ardour/editor_markers.cc:738 +#, fuzzy +msgid "ardour: rename range" +msgstr "ardour: renomear região" + +#: gtk_ardour/editor_markers.cc:792 +#, fuzzy +msgid "set loop range" +msgstr "selecionar intervalo de zoom" + +#: gtk_ardour/editor_markers.cc:818 +#, fuzzy +msgid "set punch range" +msgstr "Selecionar intervalo atual" + +#: gtk_ardour/editor_mouse.cc:99 +msgid "Editor::event_frame() used on unhandled event type %1" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1555 +msgid "programming error: start_grab called without drag item" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1760 +#, fuzzy +msgid "change fade in length" +msgstr "fade in na edição" + +#: gtk_ardour/editor_mouse.cc:1778 +msgid "programming error: fade out canvas item has no regionview data pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1852 +#, fuzzy +msgid "change fade out length" +msgstr "fade out na edição" + +#: gtk_ardour/editor_mouse.cc:1871 +msgid "programming error: cursor canvas item has no cursor data pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470 +msgid "" +"programming error: meter marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2163 +#, fuzzy +msgid "move meter mark" +msgstr "remover marca" + +#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335 +#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439 +msgid "" +"programming error: tempo marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340 +#: gtk_ardour/editor_tempodisplay.cc:425 +msgid "programming error: marker for tempo is not a tempo marker!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2245 +#, fuzzy +msgid "move tempo mark" +msgstr "remover marca" + +#: gtk_ardour/editor_mouse.cc:2388 +msgid "programming error: line canvas item has no line pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2497 +#, fuzzy +msgid "move region(s)" +msgstr "inverter horizontalmente as regiões" + +#: gtk_ardour/editor_mouse.cc:2509 +msgid "Drag region copy" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2579 +#, fuzzy +msgid "copy region(s)" +msgstr "normalizar região" + +#: gtk_ardour/editor_mouse.cc:2612 +#, fuzzy +msgid "Drag region brush" +msgstr "normalizar região" + +#: gtk_ardour/editor_mouse.cc:3425 +#, fuzzy +msgid "selection grab" +msgstr "Seleção" + +#: gtk_ardour/editor_mouse.cc:3571 +#, fuzzy +msgid "range selection" +msgstr "Reproduzir seleção" + +#: gtk_ardour/editor_mouse.cc:3587 +#, fuzzy +msgid "trim selection start" +msgstr "Desde a localização" + +#: gtk_ardour/editor_mouse.cc:3603 +#, fuzzy +msgid "trim selection end" +msgstr "Desde a localização" + +#: gtk_ardour/editor_mouse.cc:3620 +#, fuzzy +msgid "move selection" +msgstr "Saltar Seleção" + +#: gtk_ardour/editor_mouse.cc:3995 +#, fuzzy +msgid "Start point trim" +msgstr "Do início ao cursor de edição" + +#: gtk_ardour/editor_mouse.cc:4023 +msgid "End point trim" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:4062 +msgid "trimmed region" +msgstr "região aparado" + +#: gtk_ardour/editor_mouse.cc:4203 +#, fuzzy +msgid "new range marker" +msgstr "adicionar marca de intervalo" + +#: gtk_ardour/editor_mouse.cc:4422 +#, fuzzy +msgid "select regions" +msgstr "Loop região selecionada" + +#: gtk_ardour/editor_mouse.cc:4451 +msgid "Name for region:" +msgstr "Nome para a região:" + +#: gtk_ardour/editor_mouse.cc:4517 +#, fuzzy +msgid "timestretch" +msgstr "ardour: esticar no tempo" + +#: gtk_ardour/editor_ops.cc:117 +#, fuzzy +msgid "split" +msgstr "Separar" + +#: gtk_ardour/editor_ops.cc:153 +#, fuzzy +msgid "remove region" +msgstr "inverter horizontalmente as regiões" + +#: gtk_ardour/editor_ops.cc:172 +msgid "" +" This is destructive, will possibly delete audio files\n" +"It cannot be undone\n" +"Do you really want to destroy %1 ?" +msgstr "" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "these regions" +msgstr "inverter horizontalmente as regiões" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "this region" +msgstr "mutar esta região" + +#: gtk_ardour/editor_ops.cc:179 +#, fuzzy +msgid "Yes, destroy them." +msgstr "Sim, remova definitivamente isto." + +#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434 +msgid "Yes, destroy it." +msgstr "Sim, remova definitivamente isto." + +#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435 +#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300 +msgid "No, do nothing." +msgstr "Não, não faça nada." + +#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307 +#, fuzzy +msgid "extend selection" +msgstr "Separar Seleção" + +#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357 +#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427 +msgid "nudge forward" +msgstr "" + +#: gtk_ardour/editor_ops.cc:491 +msgid "build_region_boundary_cache called with snap_type = %1" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1305 +#, fuzzy +msgid "set selection from range" +msgstr "Nova região a partir da seleção" + +#: gtk_ardour/editor_ops.cc:1421 +msgid "clear markers" +msgstr "limpar marcas" + +#: gtk_ardour/editor_ops.cc:1433 +msgid "clear ranges" +msgstr "limpar intervalos" + +#: gtk_ardour/editor_ops.cc:1452 +msgid "clear locations" +msgstr "limpar localizações" + +#: gtk_ardour/editor_ops.cc:1503 +#, fuzzy +msgid "insert dragged region" +msgstr "Inserir Região" + +#: gtk_ardour/editor_ops.cc:1538 +#, fuzzy +msgid "insert region" +msgstr "Inserir Região" + +#: gtk_ardour/editor_ops.cc:1744 +msgid "ardour: rename region" +msgstr "ardour: renomear região" + +#: gtk_ardour/editor_ops.cc:1891 +msgid "You can't import an audiofile until you have a session loaded." +msgstr "" +"Você não pode importar um arquivo de áudio se tiver uma sessão carregada" + +#: gtk_ardour/editor_ops.cc:1901 +#, fuzzy +msgid "Import selected as tracks" +msgstr "Importar seleção" + +#: gtk_ardour/editor_ops.cc:1904 +#, fuzzy +msgid "Import selected to region list" +msgstr "Loop região selecionada" + +#: gtk_ardour/editor_ops.cc:1933 +msgid "ardour: audio import in progress" +msgstr "ardour: efetuando importação de áudio" + +#: gtk_ardour/editor_ops.cc:1937 +msgid "Cancel Import" +msgstr "Cancelar importação" + +#: gtk_ardour/editor_ops.cc:1944 +#, fuzzy +msgid "ardour: importing %1" +msgstr "ardour: exportar" + +#: gtk_ardour/editor_ops.cc:1990 +#, fuzzy +msgid "%1 it anyway" +msgstr "Embutir mesmo assim" + +#: gtk_ardour/editor_ops.cc:1996 +#, fuzzy +msgid "Don't %1 it" +msgstr "Não %1" + +#: gtk_ardour/editor_ops.cc:1997 +msgid "%1 all without questions" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1998 +#, fuzzy +msgid "Cancel entire import" +msgstr "Cancelar importação" + +#: gtk_ardour/editor_ops.cc:2004 +#, fuzzy +msgid "" +"%1\n" +"This audiofile's sample rate doesn't match the session sample rate!" +msgstr "" +"A freqüência de áudio deste arquivo não corresponde à freqüência da sessão!" + +#: gtk_ardour/editor_ops.cc:2032 +msgid "You can't embed an audiofile until you have a session loaded." +msgstr "" +"Você não pode embutir um arquivo de áudio se tiver uma sessão carregada" + +#: gtk_ardour/editor_ops.cc:2039 +msgid "Add to External Region list" +msgstr "Adicionar na lista de regiões" + +#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210 +#: gtk_ardour/editor_ops.cc:2286 +msgid "Editor: cannot open file \"%1\" (%2)" +msgstr "Editor: não foi possível abrir o arquivo \"%1\" (%2)" + +#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312 +msgid "could not open %1" +msgstr "não foi possível abrir %1" + +#: gtk_ardour/editor_ops.cc:2171 +#, fuzzy +msgid "Insert selected as new tracks" +msgstr "Inserir seleção" + +#: gtk_ardour/editor_ops.cc:2186 +msgid "Insert selected" +msgstr "Inserir seleção" + +#: gtk_ardour/editor_ops.cc:2327 +#, fuzzy +msgid "insert sndfile" +msgstr "Inserir arquivo de áudio externo" + +#: gtk_ardour/editor_ops.cc:2464 +#, fuzzy +msgid "separate" +msgstr "Separar Região" + +#: gtk_ardour/editor_ops.cc:2528 +#, fuzzy +msgid "trim to selection" +msgstr "Desde a localização" + +#: gtk_ardour/editor_ops.cc:2568 +msgid "region fill" +msgstr "" + +#: gtk_ardour/editor_ops.cc:2626 +#, fuzzy +msgid "fill selection" +msgstr "Reproduzir seleção continuamente" + +#: gtk_ardour/editor_ops.cc:2650 +msgid "Place the edit cursor at the desired sync point" +msgstr "Coloque o cursor de edição no ponto de sincronia desejado" + +#: gtk_ardour/editor_ops.cc:2656 +#, fuzzy +msgid "set sync from edit cursor" +msgstr "Reproduzir a partir do cursor" + +#: gtk_ardour/editor_ops.cc:2668 +#, fuzzy +msgid "remove sync" +msgstr "Remover ponto de sincronia" + +#: gtk_ardour/editor_ops.cc:2682 +#, fuzzy +msgid "naturalize" +msgstr "Normalizar" + +#: gtk_ardour/editor_ops.cc:2746 +#, fuzzy +msgid "align selection (relative)" +msgstr "Alinhamento Relativo" + +#: gtk_ardour/editor_ops.cc:2774 +#, fuzzy +msgid "align selection" +msgstr "Saltar Seleção" + +#: gtk_ardour/editor_ops.cc:2786 +#, fuzzy +msgid "align region" +msgstr "normalizar região" + +#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858 +#, fuzzy +msgid "trim to edit" +msgstr "Do início ao cursor de edição" + +#: gtk_ardour/editor_ops.cc:2909 +#, fuzzy +msgid "ardour: freeze" +msgstr "ardour: renomear região" + +#: gtk_ardour/editor_ops.cc:2914 +#, fuzzy +msgid "Cancel Freeze" +msgstr "Cancelar" + +#: gtk_ardour/editor_ops.cc:2951 +#, fuzzy +msgid "bounce range" +msgstr "intervalo" + +#: gtk_ardour/editor_ops.cc:3004 +msgid "cut" +msgstr "cortar" + +#: gtk_ardour/editor_ops.cc:3007 +msgid "copy" +msgstr "copiar" + +#: gtk_ardour/editor_ops.cc:3020 +msgid " objects" +msgstr "objetos" + +#: gtk_ardour/editor_ops.cc:3046 +msgid " range" +msgstr "intervalo" + +#: gtk_ardour/editor_ops.cc:3201 +#, fuzzy +msgid "paste" +msgstr "Colar" + +#: gtk_ardour/editor_ops.cc:3236 +#, fuzzy +msgid "paste chunk" +msgstr "Criar trecho" + +#: gtk_ardour/editor_ops.cc:3276 +#, fuzzy +msgid "duplicate region" +msgstr "Loop região selecionada" + +#: gtk_ardour/editor_ops.cc:3309 +#, fuzzy +msgid "duplicate selection" +msgstr "Saltar Seleção" + +#: gtk_ardour/editor_ops.cc:3349 +#, fuzzy +msgid "clear playlist" +msgstr "Nome para a imagem capturada" + +#: gtk_ardour/editor_ops.cc:3378 +#, fuzzy +msgid "nudge track" +msgstr "Ocultar esta trilha" + +#: gtk_ardour/editor_ops.cc:3431 +msgid "" +"Do you really want to destroy the last capture?\n" +"(This is destructive and cannot be undone)" +msgstr "" +"Você quer realmente remover definitivamente a última captura?\n" +"(Isto não poderá ser desfeito)" + +#: gtk_ardour/editor_ops.cc:3463 +#, fuzzy +msgid "normalize" +msgstr "Normalizar" + +#: gtk_ardour/editor_ops.cc:3510 +msgid "reverse regions" +msgstr "inverter horizontalmente as regiões" + +#: gtk_ardour/editor_region_list.cc:223 +#, fuzzy +msgid "hidden" +msgstr "Oculto" + +#: gtk_ardour/editor_region_list.cc:408 +msgid "Show all" +msgstr "Mostrar tudo" + +#: gtk_ardour/editor_region_list.cc:417 +msgid "Ascending" +msgstr "Ascendente" + +#: gtk_ardour/editor_region_list.cc:419 +msgid "Descending" +msgstr "Descendente" + +#: gtk_ardour/editor_region_list.cc:423 +msgid "By Region Name" +msgstr "Por Nome da Região" + +#: gtk_ardour/editor_region_list.cc:425 +msgid "By Region Length" +msgstr "Por Tamanho da Região" + +#: gtk_ardour/editor_region_list.cc:427 +msgid "By Region Position" +msgstr "Por Posição da Região" + +#: gtk_ardour/editor_region_list.cc:429 +msgid "By Region Timestamp" +msgstr "Por tempo data/hora da Região" + +#: gtk_ardour/editor_region_list.cc:431 +msgid "By Region Start in File" +msgstr "Por posição inicial da Região no arquivo" + +#: gtk_ardour/editor_region_list.cc:433 +msgid "By Region End in File" +msgstr "Por posição final da Região no arquivo" + +#: gtk_ardour/editor_region_list.cc:435 +msgid "By Source File Name" +msgstr "Por nome original do arquivo" + +#: gtk_ardour/editor_region_list.cc:437 +msgid "By Source File Length" +msgstr "Por tamanho do arquivo original" + +#: gtk_ardour/editor_region_list.cc:439 +msgid "By Source File Creation Date" +msgstr "Por data de criação do arquivo original" + +#: gtk_ardour/editor_region_list.cc:441 +msgid "By Source Filesystem" +msgstr "Por sistema de arquivos original" + +#: gtk_ardour/editor_region_list.cc:444 +msgid "Sorting" +msgstr "Ordernação" + +#: gtk_ardour/editor_region_list.cc:808 +msgid "Regions/length" +msgstr "Regiões/tamanho" + +#: gtk_ardour/editor_region_list.cc:812 +msgid "Regions/position" +msgstr "Regiões/posição" + +#: gtk_ardour/editor_region_list.cc:816 +msgid "Regions/creation" +msgstr "Regiões/criação" + +#: gtk_ardour/editor_region_list.cc:820 +msgid "Regions/start" +msgstr "Regiões/início" + +#: gtk_ardour/editor_region_list.cc:824 +msgid "Regions/end" +msgstr "Regiões/final" + +#: gtk_ardour/editor_region_list.cc:828 +msgid "Regions/file name" +msgstr "Regiões/nome do arquivo" + +#: gtk_ardour/editor_region_list.cc:832 +msgid "Regions/file size" +msgstr "Regiões/tamanho do arquivo" + +#: gtk_ardour/editor_region_list.cc:836 +msgid "Regions/file date" +msgstr "Regiões/data do arquivo" + +#: gtk_ardour/editor_region_list.cc:840 +msgid "Regions/file system" +msgstr "Regiões/sistema de arquivos" + +#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73 +#: gtk_ardour/editor_route_list.cc:231 +msgid "editor" +msgstr "editor" + +#: gtk_ardour/editor_route_list.cc:300 +msgid "Show All AbstractTracks" +msgstr "Mostrar todas as trilhas abstratas" + +#: gtk_ardour/editor_route_list.cc:301 +msgid "Hide All AbstractTracks" +msgstr "Ocultar todas as trilhas abstratas" + +#: gtk_ardour/editor_route_list.cc:302 +msgid "Show All AudioBus" +msgstr "Mostrar todos os barramentos de áudio" + +#: gtk_ardour/editor_route_list.cc:303 +msgid "Hide All AudioBus" +msgstr "Ocultar todos os barramentos de áudio" + +#: gtk_ardour/editor_rulers.cc:311 +msgid "New location marker" +msgstr "Nova marca de localização" + +#: gtk_ardour/editor_rulers.cc:312 +msgid "Clear all locations" +msgstr "Apagar todas as localizações" + +#: gtk_ardour/editor_rulers.cc:317 +msgid "Clear all ranges" +msgstr "Remover todos os intervalos" + +#: gtk_ardour/editor_rulers.cc:326 +msgid "New Tempo" +msgstr "Novo Andamento" + +#: gtk_ardour/editor_rulers.cc:327 +msgid "Clear tempo" +msgstr "Apagar andamento" + +#: gtk_ardour/editor_rulers.cc:332 +msgid "New Meter" +msgstr "Novo Meter" + +#: gtk_ardour/editor_rulers.cc:333 +msgid "Clear meter" +msgstr "Apagar meter" + +#: gtk_ardour/editor_rulers.cc:341 +msgid "Min:Secs" +msgstr "Min:Segs" + +#: gtk_ardour/editor_selection_list.cc:117 +msgid "name for chunk:" +msgstr "nome para o trecho" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Create chunk" +msgstr "Criar trecho" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Forget it" +msgstr "Esqueça isto" + +#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295 +msgid "add" +msgstr "adicionar" + +#: gtk_ardour/editor_tempodisplay.cc:276 +#, fuzzy +msgid "add tempo mark" +msgstr "adicionar marca de intervalo" + +#: gtk_ardour/editor_tempodisplay.cc:318 +#, fuzzy +msgid "add meter mark" +msgstr "adicionar marca de intervalo" + +#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383 +msgid "done" +msgstr "pronto" + +#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404 +msgid "replace tempo mark" +msgstr "" + +#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475 +msgid "programming error: marker for meter is not a meter marker!" +msgstr "" + +#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487 +#, fuzzy +msgid "remove tempo mark" +msgstr "remover marca" + +#: gtk_ardour/editor_timefx.cc:50 +msgid "Quick but Ugly" +msgstr "Rápido mas Feio" + +#: gtk_ardour/editor_timefx.cc:51 +msgid "Skip Anti-aliasing" +msgstr "Pular Anti-aliasing" + +#: gtk_ardour/editor_timefx.cc:53 +msgid "Stretch/Shrink it" +msgstr "Esticar/Encolher isto" + +#: gtk_ardour/editor_timefx.cc:57 +msgid "ardour: timestretch" +msgstr "ardour: esticar no tempo" + +#: gtk_ardour/editor_timefx.cc:58 +msgid "TimeStretchDialog" +msgstr "Diálogo esticar no tempo" + +#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83 +#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85 +msgid "TimeStretchButton" +msgstr "Botão esticar no tempo" + +#: gtk_ardour/editor_timefx.cc:86 +msgid "TimeStretchProgress" +msgstr "Progresso esticar no tempo" + +#: gtk_ardour/editor_timefx.cc:151 +msgid "timestretch cannot be started - thread creation error" +msgstr "" + +#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410 +#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189 +msgid "22.05kHz" +msgstr "22.05kHz" + +#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413 +#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949 +#: gtk_ardour/export_dialog.cc:1191 +msgid "44.1kHz" +msgstr "44.1kHz" + +#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416 +#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193 +msgid "48kHz" +msgstr "48kHz" + +#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419 +#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195 +msgid "88.2kHz" +msgstr "88.2kHz" + +#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422 +#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197 +msgid "96kHz" +msgstr "96kHz" + +#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425 +#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199 +msgid "192kHz" +msgstr "192kHz" + +#: gtk_ardour/export_dialog.cc:73 +msgid "best" +msgstr "excelente" + +#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964 +msgid "fastest" +msgstr "rapidamente" + +#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966 +msgid "linear" +msgstr "linear" + +#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968 +msgid "better" +msgstr "bom" + +#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970 +msgid "intermediate" +msgstr "intermediário" + +#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979 +msgid "Rectangular" +msgstr "Retangular" + +#: gtk_ardour/export_dialog.cc:84 +msgid "Shaped Noise" +msgstr "Perfil de Ruído" + +#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981 +msgid "Triangular" +msgstr "Triangular" + +#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336 +msgid "stereo" +msgstr "estéreo" + +#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497 +#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219 +#: gtk_ardour/utils.cc:334 +msgid "mono" +msgstr "mono" + +#: gtk_ardour/export_dialog.cc:97 +msgid "CUE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:98 +msgid "TOC" +msgstr "" + +#: gtk_ardour/export_dialog.cc:106 +msgid "FORMAT" +msgstr "FORMATO" + +#: gtk_ardour/export_dialog.cc:107 +msgid "SAMPLE RATE" +msgstr "FREQUÊNCIA DE AMOSTRAGEM" + +#: gtk_ardour/export_dialog.cc:108 +msgid "CONVERSION QUALITY" +msgstr "QUALIDADE DE CONVERSÃO" + +#: gtk_ardour/export_dialog.cc:109 +msgid "DITHER TYPE" +msgstr "TIPO DE INTERPOLAÇÃO" + +#: gtk_ardour/export_dialog.cc:110 +#, fuzzy +msgid "CD MARKER FILE TYPE" +msgstr "TIPO DE ARQUIVO" + +#: gtk_ardour/export_dialog.cc:111 +msgid "CHANNELS" +msgstr "CANAIS" + +#: gtk_ardour/export_dialog.cc:112 +msgid "FILE TYPE" +msgstr "TIPO DE ARQUIVO" + +#: gtk_ardour/export_dialog.cc:113 +msgid "SAMPLE FORMAT" +msgstr "FORMATO DE AMOSTRA" + +#: gtk_ardour/export_dialog.cc:114 +msgid "SAMPLE ENDIANNESS" +msgstr "REPRESENTAÇÃO BINÃRIA" + +#: gtk_ardour/export_dialog.cc:115 +#, fuzzy +msgid "EXPORT CD MARKER FILE ONLY" +msgstr "TIPO DE ARQUIVO" + +#: gtk_ardour/export_dialog.cc:116 +msgid "EXPORT TO FILE" +msgstr "EXPORTAR PARA ARQUIVO" + +#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118 +#: gtk_ardour/option_editor.cc:119 +msgid "Browse" +msgstr "Localizar" + +#: gtk_ardour/export_dialog.cc:119 +msgid "Specific tracks ..." +msgstr "" + +#: gtk_ardour/export_dialog.cc:131 +msgid "ardour: export" +msgstr "ardour: exportar" + +#: gtk_ardour/export_dialog.cc:132 +msgid "ardour_export" +msgstr "" + +#: gtk_ardour/export_dialog.cc:156 +#, fuzzy +msgid "Output" +msgstr "Saídas" + +#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626 +msgid "Track" +msgstr "Trilha" + +#: gtk_ardour/export_dialog.cc:287 +msgid "slereg" +msgstr "" + +#: gtk_ardour/export_dialog.cc:658 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD toc file" +msgstr "" +"Editor: não foi possível abrir o arquivo \"%1\" para exportar marcadores de " +"faixa de CD" + +#: gtk_ardour/export_dialog.cc:780 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD cue file" +msgstr "" +"Editor: não foi possível abrir o arquivo \"%1\" para exportar marcadores de " +"faixa de CD" + +#: gtk_ardour/export_dialog.cc:799 +msgid "WAV" +msgstr "" + +#: gtk_ardour/export_dialog.cc:1051 +msgid "Stop Export" +msgstr "Cancelar Exportação" + +#: gtk_ardour/gain_automation_time_axis.cc:60 +#, fuzzy +msgid "add gain automation event" +msgstr "adicionar evento de automação para " + +#: gtk_ardour/gain_meter.cc:68 +msgid "Cannot create slider pixmaps" +msgstr "" + +#: gtk_ardour/gain_meter.cc:83 +msgid "dbFS" +msgstr "" + +#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134 +#: gtk_ardour/gain_meter.cc:728 +msgid "pre" +msgstr "" + +#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724 +#, fuzzy +msgid "input" +msgstr "%1 entrada" + +#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732 +#, fuzzy +msgid "post" +msgstr "porta" + +#: gtk_ardour/gain_meter.cc:146 +msgid "tupni" +msgstr "" + +#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470 +#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537 +#, fuzzy +msgid "-inf" +msgstr "entrada" + +#: gtk_ardour/imageframe_socket_handler.cc:127 +msgid "Image Compositor Socket has been shutdown/closed" +msgstr "" + +#: gtk_ardour/imageframe_time_axis.cc:295 +#, fuzzy +msgid "0.5 seconds" +msgstr "Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259 +#, fuzzy +msgid "1 seconds" +msgstr "Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260 +#, fuzzy +msgid "1.5 seconds" +msgstr "Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261 +#, fuzzy +msgid "2 seconds" +msgstr "Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262 +#, fuzzy +msgid "2.5 seconds" +msgstr "Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263 +#, fuzzy +msgid "3 seconds" +msgstr "Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268 +#, fuzzy +msgid "Duration (sec)" +msgstr "normalizar região" + +#: gtk_ardour/imageframe_time_axis.cc:310 +#, fuzzy +msgid "Remove Frame" +msgstr "Remover Campo" + +#: gtk_ardour/imageframe_time_axis.cc:313 +#, fuzzy +msgid "Image Frame" +msgstr "Quadros" + +#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274 +#, fuzzy +msgid "Rename Track" +msgstr "Renomear" + +#: gtk_ardour/io_selector.cc:64 +msgid "%1 input" +msgstr "%1 entrada" + +#: gtk_ardour/io_selector.cc:66 +msgid "%1 output" +msgstr "%1 saída" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103 +msgid "Inputs" +msgstr "Entradas" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104 +msgid "Outputs" +msgstr "Saídas" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Input" +msgstr "adicionar entrada" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Output" +msgstr "adicionar saída" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Input" +msgstr "Remover ponto de sincronia" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Output" +msgstr "# Saídas" + +#: gtk_ardour/io_selector.cc:144 +#, fuzzy +msgid "Disconnect All" +msgstr "Desconectar" + +#: gtk_ardour/io_selector.cc:158 +msgid "Available connections" +msgstr "Conexões disponíveis" + +#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636 +#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724 +msgid "port" +msgstr "porta" + +#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587 +msgid "There are no more JACK ports available." +msgstr "" + +#: gtk_ardour/io_selector.cc:790 +msgid "ardour: " +msgstr "" + +#: gtk_ardour/keyboard.cc:419 +msgid "KeyboardTarget: keyname \"%1\" is unknown." +msgstr "KeyboardTarget: nome da tecla \"%1\" é desconhecido." + +#: gtk_ardour/keyboard.cc:645 +msgid "" +"Your system is completely broken - NumLock uses \"%1\"as its modifier. This " +"is madness - see the man page for xmodmap to find out how to fix this." +msgstr "" + +#: gtk_ardour/keyboard.cc:653 +msgid "" +"Your system generates \"%1\" when the NumLock key is pressed. This can cause " +"problems when editing so Ardour will use %2 to mean Meta rather than %1" +msgstr "" + +#: gtk_ardour/keyboard.cc:714 +msgid "You have %1 keys bound to \"mod1\"" +msgstr "Você já tem %1 atalho de teclado para \"mod1\"" + +#: gtk_ardour/keyboard.cc:729 +msgid "You have %1 keys bound to \"mod2\"" +msgstr "Você já tem %1 atalho de teclado para \"mod2\"" + +#: gtk_ardour/keyboard.cc:744 +msgid "You have %1 keys bound to \"mod3\"" +msgstr "Você já tem %1 atalho de teclado para \"mod3\"" + +#: gtk_ardour/keyboard.cc:759 +msgid "You have %1 keys bound to \"mod4\"" +msgstr "Você já tem %1 atalho de teclado para \"mod4\"" + +#: gtk_ardour/keyboard.cc:774 +msgid "You have %1 keys bound to \"mod5\"" +msgstr "Você já tem %1 atalho de teclado para \"mod5\"" + +#: gtk_ardour/keyboard_target.cc:72 +msgid "KeyboardTarget: empty string passed to add_binding." +msgstr "" + +#: gtk_ardour/keyboard_target.cc:78 +msgid "KeyboardTarget: no translation found for \"%1\"" +msgstr "KeyboardTarget: sem tradução encontrada para \"%1\"" + +#: gtk_ardour/keyboard_target.cc:83 +msgid "KeyboardTarget: unknown action \"%1\"" +msgstr "KeyboardTarget: ação desconhecida \"%1\"" + +#: gtk_ardour/keyboard_target.cc:248 +msgid "misformed binding node - ignored" +msgstr "" + +#: gtk_ardour/library_ui.cc:62 +msgid "Soundfile Library" +msgstr "Biblioteca de Ãudio" + +#: gtk_ardour/library_ui.cc:63 +msgid "Filesystem" +msgstr "Sistema de arquivos" + +#: gtk_ardour/library_ui.cc:66 +msgid "Split Channels" +msgstr "Separar Canais" + +#: gtk_ardour/library_ui.cc:69 +msgid "ardour: soundfile selector" +msgstr "ardour: seletor de arquivos de áudio" + +#: gtk_ardour/library_ui.cc:430 +msgid "Add to Library..." +msgstr "Adicionar na Biblioteca..." + +#: gtk_ardour/library_ui.cc:431 +msgid "Remove..." +msgstr "Remover..." + +#: gtk_ardour/library_ui.cc:432 +msgid "Find..." +msgstr "Buscar..." + +#: gtk_ardour/library_ui.cc:433 +msgid "Add Folder" +msgstr "Criar Diretório" + +#: gtk_ardour/library_ui.cc:434 +msgid "Add audio file or directory" +msgstr "Adicionar arquivo ou diretório" + +#: gtk_ardour/library_ui.cc:713 +msgid "Importing" +msgstr "Importando" + +#: gtk_ardour/library_ui.cc:748 +msgid "%1 not added to database" +msgstr "%1 não foi adicionada ao banco de dados" + +#: gtk_ardour/library_ui.cc:767 +msgid "Folder name:" +msgstr "Nome do diretório:" + +#: gtk_ardour/library_ui.cc:838 +msgid "Should not be reached" +msgstr "" + +#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096 +msgid "file \"%1\" could not be opened" +msgstr "arquivo \"%1\" não pôde ser aberto" + +#: gtk_ardour/library_ui.cc:956 +msgid "Field" +msgstr "Campo" + +#: gtk_ardour/library_ui.cc:957 +msgid "Value" +msgstr "Valor" + +#: gtk_ardour/library_ui.cc:973 +msgid "Stop" +msgstr "Parar" + +#: gtk_ardour/library_ui.cc:974 +msgid "Add Field..." +msgstr "Adicionar Campo..." + +#: gtk_ardour/library_ui.cc:975 +msgid "Remove Field" +msgstr "Remover Campo" + +#: gtk_ardour/library_ui.cc:979 +msgid "Soundfile Info" +msgstr "Informação do arquivo de áudio" + +#: gtk_ardour/library_ui.cc:1106 +msgid "file \"%1\" appears not to be an audio file" +msgstr "" + +#: gtk_ardour/library_ui.cc:1159 +msgid "Could not read file: %1 (%2)." +msgstr "Não foi possível ler o arquivo: %1 (%2)." + +#: gtk_ardour/library_ui.cc:1177 +msgid "Could not access soundfile: " +msgstr "não foi possível acessar arquivo de áudio" + +#: gtk_ardour/library_ui.cc:1222 +msgid "Field name:" +msgstr "Nome do campo:" + +#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367 +msgid "Field value:" +msgstr "Valor do campo:" + +#: gtk_ardour/library_ui.cc:1295 +msgid "Find" +msgstr "Buscar" + +#: gtk_ardour/library_ui.cc:1296 +msgid "AND" +msgstr "E" + +#: gtk_ardour/library_ui.cc:1297 +msgid "OR" +msgstr "OU" + +#: gtk_ardour/library_ui.cc:1300 +msgid "ardour: locate soundfiles" +msgstr "ardour: localizar arquivos de áudio" + +#: gtk_ardour/library_ui.cc:1426 +msgid "Results" +msgstr "Resultados" + +#: gtk_ardour/library_ui.cc:1427 +msgid "Uris" +msgstr "" + +#: gtk_ardour/library_ui.cc:1439 +msgid "Create multi-channel region" +msgstr "Criar região multi-canal" + +#: gtk_ardour/library_ui.cc:1442 +msgid "Ardour: Search Results" +msgstr "Ardour: Resultado da Busca" + +#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50 +msgid "Set" +msgstr "Fazer" + +#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51 +msgid "Go" +msgstr "Ir" + +#: gtk_ardour/location_ui.cc:54 +msgid "CD" +msgstr "CD" + +#: gtk_ardour/location_ui.cc:55 +msgid "Hidden" +msgstr "Oculto" + +#: gtk_ardour/location_ui.cc:57 +msgid "SCMS" +msgstr "" + +#: gtk_ardour/location_ui.cc:58 +msgid "Pre-Emphasis" +msgstr "" + +#: gtk_ardour/location_ui.cc:592 +msgid "Add New Location" +msgstr "Adicionar Nova Localização" + +#: gtk_ardour/location_ui.cc:593 +msgid "Add New Range" +msgstr "Adicionar Novo Intervalo" + +#: gtk_ardour/location_ui.cc:597 +msgid "ardour: locations" +msgstr "ardour: localizações" + +#: gtk_ardour/location_ui.cc:598 +msgid "ardour_locations" +msgstr "" + +#: gtk_ardour/location_ui.cc:629 +#, fuzzy +msgid "Location (CD Index) Markers" +msgstr "Marcas de Localização" + +#: gtk_ardour/location_ui.cc:649 +#, fuzzy +msgid "Range (CD Track) Markers" +msgstr "Marcas de Intervalos" + +#: gtk_ardour/location_ui.cc:814 +msgid "add range marker" +msgstr "adicionar marca de intervalo" + +#: gtk_ardour/main.cc:76 +msgid "ardour is killing itself for a clean exit\n" +msgstr "o ardour está se matando para uma saída limpa\n" + +#: gtk_ardour/main.cc:85 +msgid "stopping user interface\n" +msgstr "interrompendo a interface do usuário\n" + +#: gtk_ardour/main.cc:104 +#, c-format +msgid "%d(%d): received signal %d\n" +msgstr "" + +#: gtk_ardour/main.cc:190 +msgid "cannot become new process group leader (%1)" +msgstr "" + +#: gtk_ardour/main.cc:217 +msgid "cannot setup signal handling for %1" +msgstr "" + +#: gtk_ardour/main.cc:228 +msgid "cannot set default signal mask (%1)" +msgstr "" + +#: gtk_ardour/main.cc:253 +#, fuzzy +msgid "" +"Without a UI style file, ardour will look strange.\n" +" Please set ARDOUR_UI_RC to point to a valid UI style file" +msgstr "" +"Sem um arquivo de estilo o ardour vai ficar meio esquisito.\n" +"Por favor, configure a variável ambiente ARDOUR_UI_RC para um arquivo válido" + +#: gtk_ardour/main.cc:292 +msgid "" +"Ardour could not connect to JACK.\n" +"There are several possible reasons:\n" +"\n" +"1) JACK is not running.\n" +"2) JACK is running as another user, perhaps root.\n" +"3) There is already another client called \"ardour\".\n" +"\n" +"Please consider the possibilities, and perhaps (re)start JACK." +msgstr "" +"Ardour não pôde se conectar ao JACK.\n" +"Podem existir várias razões para isso:\n" +"\n" +"1) JACK não está rodando.\n" +"2) JACK está rodando como outro usuário, talvez o root.\n" +"3) Já existe um outro cliente chamado \"ardour\".\n" +"\n" +"Por favor, considere essas razões, e talvez (re)inicie o JACK." + +#: gtk_ardour/main.cc:305 +msgid "ardour: unplugged" +msgstr "ardour: desplugado" + +#: gtk_ardour/main.cc:363 +msgid "Ardour/GTK " +msgstr "" + +#: gtk_ardour/main.cc:365 +msgid "" +"\n" +" (built using " +msgstr "" + +#: gtk_ardour/main.cc:369 +#, fuzzy +msgid " with libardour " +msgstr " executando com libardour " + +#: gtk_ardour/main.cc:374 +msgid " and GCC version " +msgstr "" + +#: gtk_ardour/main.cc:384 +msgid "Copyright (C) 1999-2005 Paul Davis" +msgstr "" + +#: gtk_ardour/main.cc:385 +msgid "" +"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel " +"Baker" +msgstr "" + +#: gtk_ardour/main.cc:387 +msgid "Ardour comes with ABSOLUTELY NO WARRANTY" +msgstr "Ardour não oferece ABSOLUTAMENTE NENHUMA GARANTIA" + +#: gtk_ardour/main.cc:388 +msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +msgstr "" + +#: gtk_ardour/main.cc:389 +msgid "This is free software, and you are welcome to redistribute it " +msgstr "Isto é um Software Livre. Fique à vontade para redistribuí-lo " + +#: gtk_ardour/main.cc:390 +msgid "under certain conditions; see the source for copying conditions." +msgstr "com algumas condições; veja o fonte para mais detalhes" + +#: gtk_ardour/main.cc:399 +msgid "could not create ARDOUR GUI" +msgstr "não foi possível criar a INTERFACE ARDOUR" + +#: gtk_ardour/main.cc:419 +msgid "Could not connect to JACK server as \"%1\"" +msgstr "Não foi possível se conectar ao servidor JACK com \"%1\"" + +#: gtk_ardour/main.cc:424 +msgid "could not initialize Ardour." +msgstr "não foi possível iniciar o Ardour." + +#: gtk_ardour/main.cc:435 +msgid "could not load command line session \"%1\"" +msgstr "não foi possível carregar a sessão da linha de comando \"%1\"" + +#: gtk_ardour/main.cc:455 +msgid "" +"\n" +"\n" +"A session named \"%1\" already exists.\n" +"To avoid this message, start ardour as \"ardour %1" +msgstr "" + +#: gtk_ardour/main.cc:466 +msgid "" +"\n" +"\n" +"No session named \"%1\" exists.\n" +"To create it from the command line, start ardour as \"ardour --new %1" +msgstr "" + +#: gtk_ardour/marker.cc:354 +#, fuzzy +msgid "MarkerText" +msgstr "Marcas" + +#: gtk_ardour/marker_time_axis.cc:271 +msgid "Remove Marker" +msgstr "Remover Marca" + +#: gtk_ardour/marker_time_axis.cc:273 +msgid "Marker" +msgstr "Marca" + +#: gtk_ardour/meter_bridge.cc:74 +msgid "ardour: meter bridge" +msgstr "ardour: VU (medidor volumétrico)" + +#: gtk_ardour/meter_bridge.cc:75 +msgid "ardour_meter_bridge" +msgstr "" + +#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93 +#, c-format +msgid "# of %u-sample overs" +msgstr "" + +#: gtk_ardour/meter_bridge_strip.cc:219 +msgid "New name for meter:" +msgstr "Novo nome para VU (medidor volumétrico)" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507 +#: gtk_ardour/region_editor.cc:45 +msgid "mute" +msgstr "mudo" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508 +msgid "solo" +msgstr "solo" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506 +msgid "RECORD" +msgstr "GRAVAR" + +#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514 +msgid "polarity" +msgstr "polaridade" + +#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509 +msgid "comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810 +msgid "INPUT" +msgstr "ENTRADA" + +#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831 +msgid "OUTPUT" +msgstr "SAÃDA" + +#: gtk_ardour/mixer_strip.cc:173 +msgid "Pan automation mode" +msgstr "modo automático de pan" + +#: gtk_ardour/mixer_strip.cc:174 +msgid "Gain automation mode" +msgstr "modo automático de ganho" + +#: gtk_ardour/mixer_strip.cc:176 +msgid "Pan automation type" +msgstr "Tipo do pan automático" + +#: gtk_ardour/mixer_strip.cc:177 +msgid "Gain automation type" +msgstr "Tipo do ganho automático" + +#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232 +#: gtk_ardour/mixer_strip.cc:979 +msgid "trim" +msgstr "cortar" + +#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233 +#: gtk_ardour/mixer_strip.cc:983 +msgid "abs" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:240 +msgid "gain automation mode" +msgstr "modo automático de ganho" + +#: gtk_ardour/mixer_strip.cc:241 +msgid "pan automation mode" +msgstr "modo automático de pan" + +#: gtk_ardour/mixer_strip.cc:242 +msgid "gain automation state" +msgstr "estado do ganho automático" + +#: gtk_ardour/mixer_strip.cc:243 +msgid "pan automation state" +msgstr "estado do pan automático" + +#: gtk_ardour/mixer_strip.cc:259 +msgid "varispeed" +msgstr "velocidade variável" + +#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174 +msgid "click to add/edit comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:463 +msgid "unknown strip width \"%1\" in XML GUI information" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:522 +msgid "REC" +msgstr "GRAV" + +#: gtk_ardour/mixer_strip.cc:525 +#, fuzzy +msgid "cmt" +msgstr "cortar" + +#: gtk_ardour/mixer_strip.cc:530 +msgid "pol" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620 +#: gtk_ardour/redirect_box.cc:1180 +msgid "Not connected to JACK - no I/O changes are possible" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667 +msgid "could not register new ports required for that connection" +msgstr "não foi posível registrar portas novas solicitadas por este conneção" + +#: gtk_ardour/mixer_strip.cc:813 +msgid "IN" +msgstr "ENTRADA" + +#: gtk_ardour/mixer_strip.cc:834 +msgid "OUT" +msgstr "SAÃDA" + +#: gtk_ardour/mixer_strip.cc:950 +msgid "aplay" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:956 +msgid "awrite" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:1134 +#, fuzzy +msgid ": comment editor" +msgstr "não foi possível iniciar o editor" + +#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224 +msgid "no group" +msgstr "sem grupo" + +#: gtk_ardour/mixer_strip.cc:1227 +msgid "~G" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:52 +msgid "Strips" +msgstr "Painéis" + +#: gtk_ardour/mixer_ui.cc:56 +msgid "Snapshots" +msgstr "Capturas" + +#: gtk_ardour/mixer_ui.cc:61 +msgid "***" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17 +#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144 +#: gtk_ardour/tempo_dialog.cc:162 +msgid "Bar" +msgstr "Compasso" + +#: gtk_ardour/mixer_ui.cc:121 +msgid "Mix Groups" +msgstr "Grupos de Mixer" + +#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373 +msgid "ardour: mixer" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:192 +msgid "ardour_mixer" +msgstr "ardour_mixer" + +#: gtk_ardour/mixer_ui.cc:342 +msgid "ardour: mixer: " +msgstr "" + +#: gtk_ardour/mixer_ui.cc:641 +msgid "signal" +msgstr "sinal" + +#: gtk_ardour/mixer_ui.cc:672 +msgid "Show All AudioTrack MixerStrips" +msgstr "Mostrar painéis de mixer de todas as trilhas de áudio" + +#: gtk_ardour/mixer_ui.cc:673 +msgid "Hide All AudioTrack MixerStrips" +msgstr "Ocultar os páineis de mixer de todas as trilhas de áudio " + +#: gtk_ardour/mixer_ui.cc:674 +msgid "Show All AudioBus MixerStrips" +msgstr "Mostrar os painéis de mixer de todo os barramento de áudio" + +#: gtk_ardour/mixer_ui.cc:675 +msgid "Hide All AudioBus MixerStrips" +msgstr "Ocultar os painéis de mixer de todo os barramento de áudio" + +#: gtk_ardour/mixer_ui.cc:687 +msgid "track display list item for renamed strip not found!" +msgstr "não foi encontrada qualquer trilha para o painel de mixer" + +#: gtk_ardour/mixer_ui.cc:700 +msgid "Name for new mix group" +msgstr "Nome para o novo grupo de mixer" + +#: gtk_ardour/new_session_dialog.cc:39 +msgid "Session name:" +msgstr "Nome da sessão:" + +#: gtk_ardour/new_session_dialog.cc:39 +msgid "Create" +msgstr "Criar" + +#: gtk_ardour/new_session_dialog.cc:40 +msgid "use control outs" +msgstr "usar controles de saída" + +#: gtk_ardour/new_session_dialog.cc:41 +msgid "use master outs" +msgstr "usar saída master" + +#: gtk_ardour/new_session_dialog.cc:42 +#, fuzzy +msgid "automatically connect track inputs to physical ports" +msgstr "conectar automaticamente entradas das trilhas com as portas físicas" + +#: gtk_ardour/new_session_dialog.cc:43 +#, fuzzy +msgid "automatically connect track outputs to master outs" +msgstr "concetar automaticamente saídas das trilhas com as saídas master" + +#: gtk_ardour/new_session_dialog.cc:44 +#, fuzzy +msgid "automatically connect track outputs to physical ports" +msgstr "conectar automaticamente saídas das trilhas com as portas físicas" + +#: gtk_ardour/new_session_dialog.cc:45 +msgid "manually connect track outputs" +msgstr "conectar manualmente saídas das trilhas" + +#: gtk_ardour/new_session_dialog.cc:50 +msgid "Advanced..." +msgstr "Avançado ..." + +#: gtk_ardour/new_session_dialog.cc:52 +msgid "show again" +msgstr "mostra novamente" + +#: gtk_ardour/new_session_dialog.cc:55 +msgid "Hardware Inputs: use" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:56 +msgid "Hardware Outputs: use" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:62 +msgid "new session setup" +msgstr "nova configuração para sessão" + +#: gtk_ardour/new_session_dialog.cc:63 +msgid "ardour_new_session" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:72 +msgid "This session will playback and record at %1 Hz" +msgstr "Esta sessão será reproduzida e gravada em %1 Hz" + +#: gtk_ardour/new_session_dialog.cc:74 +msgid "" +"This rate is set by JACK and cannot be changed.\n" +"If you want to use a different sample rate\n" +"please exit and restart JACK" +msgstr "" +"A freqüência de áudio é determinada pelo JACK e não pode ser mudada.\n" +"Se você quiser usar outra freqüência de áudio\n" +"por favor feche o programa e reinicie o JACK" + +#: gtk_ardour/new_session_dialog.cc:155 +#, fuzzy +msgid "Session template" +msgstr "usar esquema existente" + +#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20 +#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146 +#: gtk_ardour/tempo_dialog.cc:164 +msgid "Location" +msgstr "Localização" + +#: gtk_ardour/new_session_dialog.cc:178 +msgid "Configuration" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:269 +msgid "blank" +msgstr "vazio" + +#: gtk_ardour/new_session_dialog.cc:328 +msgid "No template - create tracks/busses manually" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:337 +#, fuzzy +msgid "No template" +msgstr "-esquema/template" + +#: gtk_ardour/option_editor.cc:48 +#, fuzzy +msgid "Internal" +msgstr "interno" + +#: gtk_ardour/option_editor.cc:49 +#, fuzzy +msgid "Slave to MTC" +msgstr "Enviar MTC" + +#: gtk_ardour/option_editor.cc:50 +msgid "Sync with JACK" +msgstr "" + +#: gtk_ardour/option_editor.cc:51 +msgid "never used but stops crashes" +msgstr "" + +#: gtk_ardour/option_editor.cc:56 +#, fuzzy +msgid "Later regions are higher" +msgstr "Enviar região uma camada para trás" + +#: gtk_ardour/option_editor.cc:57 +msgid "Most recently added/moved/trimmed regions are higher" +msgstr "" + +#: gtk_ardour/option_editor.cc:58 +#, fuzzy +msgid "Most recently added regions are higher" +msgstr "Enviar região uma camada para trás" + +#: gtk_ardour/option_editor.cc:63 +#, fuzzy +msgid "Span entire region overlap" +msgstr "Trazer região uma camada para frente" + +#: gtk_ardour/option_editor.cc:64 +msgid "Short fades at the start of the overlap" +msgstr "" + +#: gtk_ardour/option_editor.cc:82 +#, fuzzy +msgid "Automatically create crossfades" +msgstr "Fade cruzado automático no intervalo sobreposto" + +#: gtk_ardour/option_editor.cc:83 +msgid "New full-overlap crossfades are unmuted" +msgstr "" + +#: gtk_ardour/option_editor.cc:84 +#, fuzzy +msgid "Region layering mode" +msgstr "Fim de regiões" + +#: gtk_ardour/option_editor.cc:85 +#, fuzzy +msgid "Crossfade model" +msgstr "Fade Cruzado automático" + +#: gtk_ardour/option_editor.cc:90 +msgid "Latched solo" +msgstr "Solo alternado" + +#: gtk_ardour/option_editor.cc:91 +msgid "Solo via bus" +msgstr "" + +#: gtk_ardour/option_editor.cc:96 +msgid "Show waveforms while recording" +msgstr "Mostrar formas de onda áudio quando gravando" + +#: gtk_ardour/option_editor.cc:97 +msgid "Narrow mixer strips" +msgstr "Estreitar painéis de mixer" + +#: gtk_ardour/option_editor.cc:98 +msgid "Show measure lines" +msgstr "Mostrar linhas de medida" + +#: gtk_ardour/option_editor.cc:99 +msgid "Follow playhead" +msgstr "Reproduzir a partir do início" + +#: gtk_ardour/option_editor.cc:103 +msgid "Send MTC" +msgstr "Enviar MTC" + +#: gtk_ardour/option_editor.cc:104 +msgid "Send MMC" +msgstr "Enviar MMC" + +#: gtk_ardour/option_editor.cc:105 +msgid "JACK time master" +msgstr "Modo supervisor de tempo (JACK)" + +#: gtk_ardour/option_editor.cc:107 +#, fuzzy +msgid "SMPTE offset is negative" +msgstr "Compensar SMPTE" + +#: gtk_ardour/option_editor.cc:111 +msgid "Send MIDI parameter feedback" +msgstr "" + +#: gtk_ardour/option_editor.cc:112 +msgid "MIDI parameter control" +msgstr "" + +#: gtk_ardour/option_editor.cc:113 +#, fuzzy +msgid "MMC control" +msgstr "Porta MMC" + +#: gtk_ardour/option_editor.cc:131 +#, fuzzy +msgid "Auto-connect new track inputs to hardware" +msgstr "Conectar novas faixas automaticamente" + +#: gtk_ardour/option_editor.cc:132 +#, fuzzy +msgid "Auto-connect new track outputs to hardware" +msgstr "Conectar novas faixas automaticamente" + +#: gtk_ardour/option_editor.cc:133 +#, fuzzy +msgid "Auto-connect new track outputs to master bus" +msgstr "concetar automaticamente saídas das trilhas com as saídas master" + +#: gtk_ardour/option_editor.cc:134 +#, fuzzy +msgid "Manually connect new track outputs" +msgstr "conectar manualmente saídas das trilhas" + +#: gtk_ardour/option_editor.cc:135 +msgid "Use Hardware Monitoring" +msgstr "Usar Monitoração de Hardware" + +#: gtk_ardour/option_editor.cc:136 +msgid "Use Software Monitoring" +msgstr "Usar Monitoração de Software" + +#: gtk_ardour/option_editor.cc:137 +msgid "Stop plugins with transport" +msgstr "Suspender efeitos/plugins em transporte" + +#: gtk_ardour/option_editor.cc:138 +msgid "Run plugins while recording" +msgstr "Executar plugins enquanto grava" + +#: gtk_ardour/option_editor.cc:139 +#, fuzzy +msgid "Verify remove last capture" +msgstr "Remover última captura" + +#: gtk_ardour/option_editor.cc:140 +msgid "Stop recording on xrun" +msgstr "Suspender gravaçãoo em caso de falha sincrônica (XRUN)" + +#: gtk_ardour/option_editor.cc:141 +msgid "Stop transport at end of session" +msgstr "Suspender o transporte no final da sessão" + +#: gtk_ardour/option_editor.cc:142 +msgid "Debug keyboard events" +msgstr "Debug eventos do teclado" + +#: gtk_ardour/option_editor.cc:143 +msgid "-12dB gain reduction for ffwd/rew" +msgstr "" + +#: gtk_ardour/option_editor.cc:152 +msgid "ardour: options editor" +msgstr "ardour: preferências" + +#: gtk_ardour/option_editor.cc:153 +msgid "ardour_option_editor" +msgstr "" + +#: gtk_ardour/option_editor.cc:183 +msgid "Misc" +msgstr "Miscelânea" + +#: gtk_ardour/option_editor.cc:184 +msgid "Sync" +msgstr "Sincronia" + +#: gtk_ardour/option_editor.cc:185 +msgid "Paths/Files" +msgstr "Diretórios/Arquivos" + +#: gtk_ardour/option_editor.cc:186 +msgid "Display" +msgstr "Visualização" + +#: gtk_ardour/option_editor.cc:187 +msgid "Kbd/Mouse" +msgstr "Teclado/Mouse" + +#: gtk_ardour/option_editor.cc:188 +msgid "Click" +msgstr "Metrônomo" + +#: gtk_ardour/option_editor.cc:190 +msgid "Layers & Fades" +msgstr "" + +#: gtk_ardour/option_editor.cc:195 +msgid "MIDI" +msgstr "MIDI" + +#: gtk_ardour/option_editor.cc:268 +msgid "24 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:270 +msgid "25 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:272 +msgid "30 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:278 +msgid "30 FPS drop" +msgstr "" + +#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379 +#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736 +#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800 +msgid "Medium" +msgstr "" + +#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738 +#: gtk_ardour/option_editor.cc:804 +#, fuzzy +msgid "Faster" +msgstr "Fades" + +#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714 +#: gtk_ardour/option_editor.cc:776 +#, fuzzy +msgid "Short" +msgstr "porta" + +#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716 +#: gtk_ardour/option_editor.cc:780 +msgid "Long" +msgstr "" + +#: gtk_ardour/option_editor.cc:396 +msgid "Broadcast WAVE/floating point" +msgstr "Broadcast WAVE/vírgula flutuante" + +#: gtk_ardour/option_editor.cc:397 +msgid "WAVE/floating point" +msgstr "WAVE/vírgula flutuante" + +#: gtk_ardour/option_editor.cc:417 +msgid "session RAID path" +msgstr "diretório para sessão RAID" + +#: gtk_ardour/option_editor.cc:422 +msgid "Native Format" +msgstr "Formato Nativo" + +#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460 +#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409 +msgid "internal" +msgstr "interno" + +#: gtk_ardour/option_editor.cc:537 +msgid "Short crossfade length (msecs)" +msgstr "" + +#: gtk_ardour/option_editor.cc:710 +msgid "Meter Peak Hold" +msgstr "" + +#: gtk_ardour/option_editor.cc:730 +msgid "Meter Falloff" +msgstr "" + +#: gtk_ardour/option_editor.cc:847 +msgid "Positional Sync" +msgstr "" + +#: gtk_ardour/option_editor.cc:902 +msgid "SMPTE Frames/second" +msgstr "SMPTE Frames/segundo" + +#: gtk_ardour/option_editor.cc:903 +msgid "SMPTE Offset" +msgstr "Compensar SMPTE" + +#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013 +#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211 +#, fuzzy +msgid "online" +msgstr "linear" + +#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014 +#: gtk_ardour/option_editor.cc:1208 +#, fuzzy +msgid "offline" +msgstr "linear" + +#: gtk_ardour/option_editor.cc:1319 +msgid "Use as click" +msgstr "Usar com metrônomo" + +#: gtk_ardour/option_editor.cc:1344 +msgid "Use as click emphasis" +msgstr "Usar com metrônomo acentuado" + +#: gtk_ardour/option_editor.cc:1478 +msgid "--unknown--" +msgstr "--desconhecido--" + +#: gtk_ardour/option_editor.cc:1595 +msgid "Click audio file" +msgstr "Metrônomo no arquivo de áudio" + +#: gtk_ardour/option_editor.cc:1601 +msgid "Click emphasis audiofile" +msgstr "Metrônomo acentuado no arquivo de áudio" + +#: gtk_ardour/option_editor.cc:1638 +msgid "" +"The auditioner is a dedicated mixer strip used\n" +"for listening to specific regions outside the context\n" +"of the overall mix. It can be connected just like any\n" +"other mixer strip." +msgstr "" +"O auditor é um painel de mistura dedicado\n" +"à escuta de determinadas regiões fora do contexto\n" +"da mistura geral. Pode ser interconectado tal como\n" +"qualquer outro painel de mistura." + +#: gtk_ardour/option_editor.cc:1887 +msgid "Edit using" +msgstr "Editar com" + +#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924 +msgid "+ button" +msgstr "+ button" + +#: gtk_ardour/option_editor.cc:1917 +msgid "Delete using" +msgstr "Apagar com" + +#: gtk_ardour/option_editor.cc:1947 +msgid "Ignore snap using" +msgstr "Ignorar ajuste com" + +#: gtk_ardour/opts.cc:46 +msgid "Usage: " +msgstr "Usual: " + +#: gtk_ardour/opts.cc:47 +msgid " -v, --version Show version information\n" +msgstr " -v, --version Mostra informação sobre a versão\n" + +#: gtk_ardour/opts.cc:48 +msgid " -h, --help Print this message\n" +msgstr " -h, --help Mostra esta mensagem\n" + +#: gtk_ardour/opts.cc:49 +msgid "" +" -b, --bindings Print all possible keyboard binding " +"names\n" +msgstr "" +" -b, --bindings Mostra todos os atalhos de teclado " +"possíveis nomes\n" + +#: gtk_ardour/opts.cc:50 +#, fuzzy +msgid " -n, --show-splash Show splash screen\n" +msgstr " -n, --no-splash Não mostra imagem de abertura\n" + +#: gtk_ardour/opts.cc:51 +#, fuzzy +msgid "" +" -c, --name name Use a specific jack client name, default " +"is ardour\n" +msgstr "" +" -c, --jack-client-name nome Use o cliente jack especificado por nome. " +"O padrão é o ardour\n" + +#: gtk_ardour/opts.cc:52 +#, fuzzy +msgid "" +" -N, --new session-name Create a new session from the command " +"line\n" +msgstr " [session-name] Nome da sessão para carregar\n" + +#: gtk_ardour/opts.cc:53 +msgid "" +" -o, --use-hw-optimizations Try to use h/w specific optimizations\n" +msgstr "" + +#: gtk_ardour/opts.cc:55 +#, fuzzy +msgid " -V, --novst Do not use VST support\n" +msgstr " -n, --no-splash Não mostra imagem de abertura\n" + +#: gtk_ardour/opts.cc:57 +msgid " [session-name] Name of session to load\n" +msgstr " [session-name] Nome da sessão para carregar\n" + +#: gtk_ardour/opts.cc:58 +msgid " -C, --curvetest filename Curve algorithm debugger\n" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:58 +msgid "You can't graphically edit panning of more than stream" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:78 +#, fuzzy +msgid "add pan automation event" +msgstr "adicionar evento de automação para " + +#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441 +msgid "Bypass" +msgstr "Ignorar" + +#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222 +#, fuzzy +msgid "link" +msgstr "entrada" + +#: gtk_ardour/panner_ui.cc:103 +msgid "panning link control" +msgstr "" + +#: gtk_ardour/panner_ui.cc:105 +msgid "panning link direction" +msgstr "" + +#: gtk_ardour/panner_ui.cc:232 +msgid "L" +msgstr "" + +#: gtk_ardour/panner_ui.cc:344 +#, c-format +msgid "panner for channel %u" +msgstr "" + +#: gtk_ardour/panner_ui.cc:451 +msgid "Reset all" +msgstr "reiniciar todos" + +#: gtk_ardour/playlist_selector.cc:46 +msgid "Playlists grouped by track" +msgstr "" + +#: gtk_ardour/playlist_selector.cc:53 +msgid "close" +msgstr "fechar" + +#: gtk_ardour/playlist_selector.cc:59 +#, fuzzy +msgid "ardour: playlists" +msgstr "ardour: plugins" + +#: gtk_ardour/playlist_selector.cc:104 +#, fuzzy +msgid "ardour: playlist for " +msgstr "ardour: plugins" + +#: gtk_ardour/playlist_selector.cc:122 +msgid "Other tracks" +msgstr "Outras trilhas" + +# msgstr "Ocultar esta trilha" +#: gtk_ardour/playlist_selector.cc:138 +msgid "unassigned" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:41 +msgid "Available LADSPA plugins" +msgstr "LADSPA plugins disponíveis" + +#: gtk_ardour/plugin_selector.cc:42 +msgid "Type" +msgstr "Tipo" + +#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51 +msgid "# Inputs" +msgstr "# Entradas" + +#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52 +msgid "# Outputs" +msgstr "# Saídas" + +#: gtk_ardour/plugin_selector.cc:50 +msgid "Available VST plugins" +msgstr "VST plugins disponíveis" + +#: gtk_ardour/plugin_selector.cc:58 +msgid "To be added" +msgstr "Para ser adicionada" + +#: gtk_ardour/plugin_selector.cc:72 +msgid "ardour: plugins" +msgstr "ardour: plugins" + +#: gtk_ardour/plugin_selector.cc:82 +msgid "Add a plugin to the effect list" +msgstr "Adicionar plugin na lista de efeitos" + +#: gtk_ardour/plugin_selector.cc:84 +msgid "Remove a plugin from the effect list" +msgstr "Remover plugin da lista de efeitos" + +#: gtk_ardour/plugin_selector.cc:88 +msgid "Update" +msgstr "Atualizar" + +#: gtk_ardour/plugin_selector.cc:89 +msgid "Update available plugins" +msgstr "Atualizar plugins disponíveis" + +#: gtk_ardour/plugin_selector.cc:110 +msgid "LADSPA" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:113 +msgid "VST" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:83 +msgid "" +"unknown type of editor-supplying plugin (note: no VST support in this " +"version of ardour)" +msgstr "" +"tipo desconhecido do plugin fornecido para o editor (nota: sem suporte VST " +"nesta versão do ardour)" + +#: gtk_ardour/plugin_ui.cc:269 +msgid "Plugin Editor: could not build control element for port %1" +msgstr "" +"Plugin Editor: não foi possível construir elemento de controle para a porta %" +"1" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "in" +msgstr "entrada" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "ins" +msgstr "entradas" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "out" +msgstr "saída" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "outs" +msgstr "saídas" + +#: gtk_ardour/plugin_ui.cc:382 +msgid "automation control" +msgstr "controle de automação" + +#: gtk_ardour/plugin_ui.cc:869 +#, fuzzy +msgid "save" +msgstr "Salvar" + +#: gtk_ardour/plugin_ui.cc:870 +msgid "bypass" +msgstr "ignorar" + +#: gtk_ardour/plugin_ui.cc:892 +msgid "Plugin preset %1 not found" +msgstr "Pré-seleção do plugin %1 não encontrada" + +#: gtk_ardour/plugin_ui.cc:903 +msgid "Name for plugin settings:" +msgstr "Nome para efeito/plugin" + +#: gtk_ardour/redirect_automation_line.cc:53 +msgid "redirect automation created for non-plugin" +msgstr "redirecionamento automático criado para um não-efeito/não-plugin" + +#: gtk_ardour/redirect_automation_time_axis.cc:92 +msgid "add automation event to " +msgstr "adicionar evento de automação para " + +#: gtk_ardour/redirect_box.cc:213 +msgid "New send" +msgstr "" + +#: gtk_ardour/redirect_box.cc:214 +#, fuzzy +msgid "Show send controls" +msgstr "Velocidade do controle" + +#: gtk_ardour/redirect_box.cc:360 +msgid "New Plugin ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:361 +#, fuzzy +msgid "New Insert" +msgstr "nova entrada" + +#: gtk_ardour/redirect_box.cc:362 +msgid "New Send ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:380 +#, fuzzy +msgid "Select all" +msgstr "Selecionar Tudo" + +#: gtk_ardour/redirect_box.cc:381 +#, fuzzy +msgid "Deselect all" +msgstr "Selecionar Tudo" + +#: gtk_ardour/redirect_box.cc:389 +#, fuzzy +msgid "Inserts" +msgstr "Inverter verticalmente" + +#: gtk_ardour/redirect_box.cc:390 +#, fuzzy +msgid "Sends" +msgstr "Segundos" + +#: gtk_ardour/redirect_box.cc:393 +#, fuzzy +msgid "Select all ..." +msgstr "Selecionar Tudo" + +#: gtk_ardour/redirect_box.cc:406 +#, fuzzy +msgid "Activate All" +msgstr "Ativar" + +#: gtk_ardour/redirect_box.cc:407 +#, fuzzy +msgid "Deactivate All" +msgstr "Desativar" + +#: gtk_ardour/redirect_box.cc:488 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point, there are\n" +"%3 active signal streams.\n" +"\n" +"This makes no sense - you are throwing away\n" +"part of the signal." +msgstr "" + +#: gtk_ardour/redirect_box.cc:500 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point there are\n" +"only %3 active signal streams.\n" +"\n" +"This makes no sense - unless the plugin supports\n" +"side-chain inputs. A future version of Ardour will\n" +"support this type of configuration." +msgstr "" + +#: gtk_ardour/redirect_box.cc:513 +msgid "" +"You attempted to add a plugin (%1).\n" +"\n" +"The I/O configuration doesn't make sense:\n" +"\n" +"The plugin has %2 inputs and %3 outputs.\n" +"The track/bus has %4 inputs and %5 outputs.\n" +"The insertion point, has %6 active signals.\n" +"\n" +"Ardour does not understand what to do in such situations.\n" +msgstr "" + +#: gtk_ardour/redirect_box.cc:616 +msgid "Pre-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:619 +msgid "Post-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:781 +msgid "" +"You cannot reorder this set of redirects\n" +"in that way because the inputs and\n" +"outputs do not work correctly." +msgstr "" + +#: gtk_ardour/redirect_box.cc:903 +#, fuzzy +msgid "ardour: rename redirect" +msgstr "ardour: renomear região" + +#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043 +msgid "" +"Copying the set of redirects on the clipboard failed,\n" +"probably because the I/O configuration of the plugins\n" +"could not match the configuration of this track." +msgstr "" + +#: gtk_ardour/redirect_box.cc:1064 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this track?\n" +"(this cannot be undone)" +msgstr "" +"Tem certeza de que deseja remover a trilha \"%1\" ?\n" +"(não será possível voltar)" + +#: gtk_ardour/redirect_box.cc:1067 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this bus?\n" +"(this cannot be undone)" +msgstr "" +"Tem certeza de que deseja remover a trilha \"%1\" ?\n" +"(não será possível voltar)" + +#: gtk_ardour/redirect_box.cc:1071 +#, fuzzy +msgid "Yes, remove them all" +msgstr "Sim, remova isto." + +#: gtk_ardour/redirect_box.cc:1114 +#, fuzzy +msgid "ardour: %1" +msgstr "ardour: relógio" + +#: gtk_ardour/redirect_box.cc:1156 +#, fuzzy +msgid "ardour: %1: %2 (by %3)" +msgstr "ardour: região" + +#: gtk_ardour/region_editor.cc:43 +msgid "NAME:" +msgstr "NOME:" + +#: gtk_ardour/region_editor.cc:44 +msgid "lock" +msgstr "bloquear" + +#: gtk_ardour/region_editor.cc:46 +msgid "opaque" +msgstr "opaco" + +#: gtk_ardour/region_editor.cc:49 +msgid "Layer" +msgstr "Camada" + +#: gtk_ardour/region_editor.cc:57 +msgid "ENVELOPE" +msgstr "ENVELOPE" + +#: gtk_ardour/region_editor.cc:108 +msgid "mute this region" +msgstr "mutar esta região" + +#: gtk_ardour/region_editor.cc:109 +msgid "regions underneath this one cannot be heard" +msgstr "regiões abaixo desta não são ouvidas" + +#: gtk_ardour/region_editor.cc:110 +msgid "prevent any changes to this region" +msgstr "bloquear qualquer ateração nesta região" + +#: gtk_ardour/region_editor.cc:111 +msgid "use the gain envelope during playback" +msgstr "usar envelope de ganho durante a reprodução" + +#: gtk_ardour/region_editor.cc:112 +msgid "show the gain envelope" +msgstr "mostrar envelope de ganho" + +#: gtk_ardour/region_editor.cc:113 +msgid "use fade in curve during playback" +msgstr "usar curva de fade-in durante reprodução" + +#: gtk_ardour/region_editor.cc:114 +msgid "use fade out curve during playback" +msgstr "usar curva de fade-out durante reprodução" + +#: gtk_ardour/region_editor.cc:115 +msgid "audition this region" +msgstr "ouvir esta região" + +#: gtk_ardour/region_editor.cc:148 +msgid "START:" +msgstr "INICIO" + +#: gtk_ardour/region_editor.cc:150 +msgid "END:" +msgstr "FINAL:" + +#: gtk_ardour/region_editor.cc:152 +msgid "LENGTH:" +msgstr "TAMANHO:" + +#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198 +#: gtk_ardour/region_editor.cc:234 +msgid "active" +msgstr "ativo" + +#: gtk_ardour/region_editor.cc:179 +msgid "visible" +msgstr "visível" + +#: gtk_ardour/region_editor.cc:197 +msgid "FADE IN" +msgstr "FADE IN" + +#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235 +msgid "msecs" +msgstr "milisecs." + +#: gtk_ardour/region_editor.cc:233 +msgid "FADE OUT" +msgstr "FADE OUT" + +#: gtk_ardour/region_editor.cc:276 +msgid "ardour: region " +msgstr "ardour: região" + +#: gtk_ardour/region_editor.cc:410 +msgid "fade in edit" +msgstr "fade in na edição" + +#: gtk_ardour/region_editor.cc:422 +msgid "fade out edit" +msgstr "fade out na edição" + +#: gtk_ardour/regionview.cc:1169 +#, fuzzy +msgid "add gain control point" +msgstr "Remover ponto de controlo" + +#: gtk_ardour/route_params_ui.cc:58 +msgid "Tracks/Buses" +msgstr "Trilhas/Barramentos" + +#: gtk_ardour/route_params_ui.cc:59 +msgid "Pre Redirects" +msgstr "Pré Redirecionamentos" + +#: gtk_ardour/route_params_ui.cc:60 +msgid "Post Redirects" +msgstr "Pós Redirecionamentos" + +#: gtk_ardour/route_params_ui.cc:105 +#, fuzzy +msgid "Pre-fader Redirects" +msgstr "Pré Redirecionamentos" + +#: gtk_ardour/route_params_ui.cc:106 +#, fuzzy +msgid "Post-fader Redirects" +msgstr "Pós Redirecionamentos" + +#: gtk_ardour/route_params_ui.cc:138 +#, fuzzy +msgid "ardour: track/bus inspector" +msgstr "ardour: adicionar trilhas/barramento" + +#: gtk_ardour/route_params_ui.cc:139 +msgid "ardour_route_parameters" +msgstr "ardour_route_parameters" + +#: gtk_ardour/route_params_ui.cc:189 +msgid "route display list item for renamed route not found!" +msgstr "não foi encontrada qualquer elemento para encaminhamento" + +#: gtk_ardour/route_params_ui.cc:448 +msgid "NO TRACK" +msgstr "NENHUMA TRILHA" + +#: gtk_ardour/route_params_ui.cc:669 +#, fuzzy +msgid "ardour: track/bus inspector: " +msgstr "ardour: adicionar trilhas/barramento" + +#: gtk_ardour/route_params_ui.cc:673 +msgid "No Route Selected" +msgstr "Caminho não selecionado" + +#: gtk_ardour/route_params_ui.cc:674 +#, fuzzy +msgid "ardour: track/bus/inspector: no route selected" +msgstr "ardour: parâmetros de encaminhamento: caminho não seleccionado" + +#: gtk_ardour/route_ui.cc:134 +#, fuzzy +msgid "mute change" +msgstr "Fazer intervalo de inserção" + +#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220 +#, fuzzy +msgid "solo change" +msgstr "Loop no intervalo" + +#: gtk_ardour/route_ui.cc:284 +msgid "rec-enable change" +msgstr "" + +#: gtk_ardour/route_ui.cc:423 +#, fuzzy +msgid "Solo-safe" +msgstr "Solo" + +#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474 +#, fuzzy +msgid "MIDI Bind" +msgstr "MIDI" + +#: gtk_ardour/route_ui.cc:445 +msgid "Pre Fader" +msgstr "Pré Fade" + +#: gtk_ardour/route_ui.cc:452 +msgid "Post Fader" +msgstr "Pós Fade" + +#: gtk_ardour/route_ui.cc:459 +msgid "Control Outs" +msgstr "Controle de Saídas" + +#: gtk_ardour/route_ui.cc:466 +msgid "Main Outs" +msgstr "Saídas Principais" + +#: gtk_ardour/route_ui.cc:503 +msgid "mix group solo change" +msgstr "" + +#: gtk_ardour/route_ui.cc:537 +msgid "mix group mute change" +msgstr "" + +#: gtk_ardour/route_ui.cc:553 +msgid "mix group rec-enable change" +msgstr "" + +#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258 +msgid "ardour: color selection" +msgstr "ardour: seleção de cor" + +#: gtk_ardour/route_ui.cc:652 +#, fuzzy +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"You may also lose the playlist used by this track.\n" +"(cannot be undone)" +msgstr "" +"Tem certeza de que deseja remover a trilha \"%1\" ?\n" +"(não será possível voltar)" + +#: gtk_ardour/route_ui.cc:654 +msgid "" +"Do you really want to remove bus \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Deseja realmente remover o barramento \"%1\" ?\n" +"(esta operação não poderá ser desfeita)" + +#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299 +msgid "Yes, remove it." +msgstr "Sim, remova isto." + +#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358 +msgid "new name: " +msgstr "novo nome: " + +#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31 +msgid "Beats per minute" +msgstr "Batimentos por minuto" + +#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35 +#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163 +msgid "Beat" +msgstr "Batimentos" + +#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158 +msgid "Meter denominator" +msgstr "Denominador métrico" + +#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159 +msgid "Beats per bar" +msgstr "Batimentos por compasso" + +#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189 +msgid "whole (1)" +msgstr "toda (1)" + +#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191 +msgid "second (2)" +msgstr "segunda (2)" + +#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193 +msgid "third (3)" +msgstr "terceira (3)" + +#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195 +#: gtk_ardour/tempo_dialog.cc:203 +msgid "quarter (4)" +msgstr "quarta (4)" + +#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197 +msgid "eighth (8)" +msgstr "oitava (8)" + +#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199 +msgid "sixteenth (16)" +msgstr "décima sexta (16)" + +#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201 +msgid "thirty-second (32)" +msgstr "trigésima segunda (32)" + +#: gtk_ardour/tempo_dialog.cc:301 +msgid "garbaged note type entry (%1)" +msgstr "tipo de nota entrada descartada (%1)" + +#: gtk_ardour/tempo_dialog.cc:311 +msgid "incomprehensible note type entry (%1)" +msgstr "tipo de nota entrada incompreensível (%1)" + +#: gtk_ardour/time_axis_view.cc:95 +msgid "gTortnam" +msgstr "gTortnam" + +#: gtk_ardour/time_axis_view.cc:446 +msgid "Largest" +msgstr "Enorme" + +#: gtk_ardour/time_axis_view.cc:447 +msgid "Large" +msgstr "Grande" + +#: gtk_ardour/time_axis_view.cc:448 +msgid "Larger" +msgstr "Maior" + +#: gtk_ardour/time_axis_view.cc:450 +msgid "Smaller" +msgstr "Menor" + +#: gtk_ardour/time_axis_view.cc:451 +msgid "Small" +msgstr "Pequeno" + +#: gtk_ardour/time_axis_view.cc:785 +msgid "unknown track height name \"%1\" in XML GUI information" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:69 +msgid "TimeAxisViewItemName" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:258 +msgid "new duration %1 frames is out of bounds for %2" +msgstr "" + +#: gtk_ardour/time_selection.cc:40 +msgid "programming error: request for non-existent audio range (%1)!" +msgstr "" + +#: gtk_ardour/utils.cc:57 +msgid "" +"\"\n" +"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+=" +msgstr "" + +#: gtk_ardour/utils.cc:66 +msgid "aeiou" +msgstr "" + +#: gtk_ardour/utils.cc:75 +msgid "AEIOU" +msgstr "" + +#: gtk_ardour/utils.cc:84 +msgid "bcdfghjklmnpqrtvwxyz" +msgstr "" + +#: gtk_ardour/utils.cc:93 +msgid "BCDFGHJKLMNPQRTVWXYZ" +msgstr "" + +#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265 +msgid "bad XPM header %1" +msgstr "" + +#: gtk_ardour/utils.cc:516 +msgid "missing RGBA style for \"%1\"" +msgstr "" + +#: gtk_ardour/visual_time_axis.cc:297 +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Tem certeza de que deseja remover a trilha \"%1\" ?\n" +"(não será possível voltar)" + +#: gtk_ardour/visual_time_axis.cc:385 +msgid "A track already exists with that name" +msgstr "já existe uma trilha com este nome" + +#~ msgid "Seamless Looping" +#~ msgstr "Fazendo loop sem emendas" + +#~ msgid "Export to CD" +#~ msgstr "Exportar para CD" + +#~ msgid "No toggle button pixmaps found to match toggle-button-[0-9]*.xpm$" +#~ msgstr "" +#~ "Nenhum ícone de pressionamento foi encontrado para o toggle-button-[0-9]*." +#~ "xpm$" + +#~ msgid "" +#~ "No small push button pixmaps found to match small-round-button-[0-9]*.xpm$" +#~ msgstr "" +#~ "Nenhum ícone de pressionamento foi encontrado para o small-round-button-" +#~ "[0-9]*.xpm$" + +#~ msgid "No pixmaps found to match hslider[0-9]*.xpm$" +#~ msgstr "Nenhum ícone encontrado para hslider[0-9]*.xpm$" + +#~ msgid "No pixmaps found to match vslider[0-9]*.xpm$" +#~ msgstr "Nenhum ícone encontrado para vslider[0-9]*.xpm$" + +#~ msgid "Trace MIDI Input" +#~ msgstr "Rastrear Entrada MIDI" + +#~ msgid "Trace MIDI Output" +#~ msgstr "Rastrear Saída MIDI" + +#~ msgid "MTC Port" +#~ msgstr "Porta MTC" + +#~ msgid "attempt to timestretch a non-audio track!" +#~ msgstr "tentativa de esticar temporalmente uma faixa não-áudio" + +#~ msgid "ok" +#~ msgstr "ok" + +#~ msgid "apply" +#~ msgstr "aplicar" + +#~ msgid "fade" +#~ msgstr "fade" + +#~ msgid "Edit left" +#~ msgstr "Editar a esquerda" + +#~ msgid "Edit right" +#~ msgstr "Editar a direita" + +#~ msgid "Edit fade" +#~ msgstr "Editar fade" + +#~ msgid "Export region" +#~ msgstr "Exportar região" + +#, fuzzy +#~ msgid "Bounce region" +#~ msgstr "Saltar Seleção" + +#~ msgid "Region" +#~ msgstr "Região" + +#~ msgid "Play selected region" +#~ msgstr "Reproduzir região selecionada" + +#~ msgid "clear connections" +#~ msgstr "limpar conexões" + +#~ msgid "Crossfades in use" +#~ msgstr "Fade Cruzado em uso" + +#, fuzzy +#~ msgid "outside this computer" +#~ msgstr "Ocultar esta trilha" + +#, fuzzy +#~ msgid "inside this computer" +#~ msgstr "Ocultar esta trilha" diff --git a/gtk2_ardour/po/pt_PT.po b/gtk2_ardour/po/pt_PT.po new file mode 100644 index 0000000000..aa3904beaf --- /dev/null +++ b/gtk2_ardour/po/pt_PT.po @@ -0,0 +1,5094 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Paul Davis +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: 0.814.2\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2005-09-19 18:09-0400\n" +"PO-Revision-Date: 2004-12-07 13:00+0000\n" +"Last-Translator: Rui Nuno Capela \n" +"Language-Team: Portuguese\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: gtk_ardour/about.cc:134 +msgid "Marcus Andersson" +msgstr "" + +#: gtk_ardour/about.cc:135 +msgid "Jeremy Hall" +msgstr "" + +#: gtk_ardour/about.cc:136 +msgid "Steve Harris" +msgstr "" + +#: gtk_ardour/about.cc:137 +msgid "Tim Mayberry" +msgstr "" + +#: gtk_ardour/about.cc:138 +msgid "Mark Stewart" +msgstr "" + +#: gtk_ardour/about.cc:139 +msgid "Sam Chessman" +msgstr "" + +#: gtk_ardour/about.cc:140 +msgid "Jack O'Quin" +msgstr "" + +#: gtk_ardour/about.cc:141 +msgid "Matt Krai" +msgstr "" + +#: gtk_ardour/about.cc:142 +msgid "Ben Bell" +msgstr "" + +#: gtk_ardour/about.cc:143 +msgid "Gerard van Dongen" +msgstr "" + +#: gtk_ardour/about.cc:144 +msgid "Thomas Charbonnel" +msgstr "" + +#: gtk_ardour/about.cc:145 +msgid "Nick Mainsbridge" +msgstr "" + +#: gtk_ardour/about.cc:146 +msgid "Colin Law" +msgstr "" + +#: gtk_ardour/about.cc:147 +msgid "Sampo Savolainen" +msgstr "" + +#: gtk_ardour/about.cc:148 +msgid "Joshua Leach" +msgstr "" + +#: gtk_ardour/about.cc:149 +msgid "Rob Holland" +msgstr "" + +#: gtk_ardour/about.cc:150 +msgid "Per Sigmond" +msgstr "" + +#: gtk_ardour/about.cc:151 +msgid "Doug Mclain" +msgstr "" + +#: gtk_ardour/about.cc:156 +msgid "" +"French:\n" +"\tAlain Fréhel " +msgstr "" + +#: gtk_ardour/about.cc:157 +msgid "" +"German:\n" +"\tKarsten Petersen " +msgstr "" + +#: gtk_ardour/about.cc:158 +msgid "" +"Italian:\n" +"\tFilippo Pappalardo " +msgstr "" + +#: gtk_ardour/about.cc:159 +msgid "" +"Portuguese:\n" +"\tRui Nuno Capela " +msgstr "" + +#: gtk_ardour/about.cc:160 +msgid "" +"Brazilian Portuguese:\n" +"\tAlexander da Franca Fernandes \n" +"\tChris Ross " +msgstr "" + +#: gtk_ardour/about.cc:162 +msgid "" +"Spanish:\n" +"\t Alex Krohn " +msgstr "" + +#: gtk_ardour/about.cc:163 +msgid "" +"Russian:\n" +"\t Igor Blinov " +msgstr "" + +#: gtk_ardour/about.cc:181 +#, fuzzy +msgid "" +"Copyright (C) 1999-2005 Paul Davis\n" +"Ardour comes with ABSOLUTELY NO WARRANTY\n" +"This is free software, and you are welcome to redistribute it\n" +"under certain conditions; see the file COPYING for details.\n" +msgstr "" +"Copyright (C) 1999-2004 Paul Davis\n" +"Ardour é fornecido ABSOLUTAMENTE SEM QUALQUER GARANTIA\n" +"Sendo software livre, é permitida e até encorajada a sua distribuição\n" +"desde que sejam respeitadas algumas condições;\n" +"para mais informações, leia por favor o ficheiro COPYING.\n" + +#: gtk_ardour/about.cc:188 +#, fuzzy +msgid "" +"Ardour: %1\n" +"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)" +msgstr "" +"Ardour: %1\n" +"(compilado com ardour/gtk %2 libardour: %3.%4.%5)" + +#: gtk_ardour/about.cc:206 +msgid "" +"Primary author:\n" +"\tPaul Davis\n" +"\n" +"Major developers:\n" +"\tJesse Chappell\n" +"\tTaybin Rutkin\n" +"Contributors:\n" +"\t" +msgstr "" + +#: gtk_ardour/about.cc:243 +msgid "Authors" +msgstr "Autores" + +#: gtk_ardour/about.cc:244 +msgid "Translators" +msgstr "Tradutores" + +#: gtk_ardour/about.cc:361 +msgid "cannot open splash image file \"%1\"" +msgstr "" +"Editor: não foi possível abrir o ficheiro de imagem inicial \"%1\" (%2)" + +#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33 +#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81 +#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977 +#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85 +#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777 +#: gtk_ardour/redirect_box.cc:900 +msgid "OK" +msgstr "" + +#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92 +#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046 +#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72 +#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982 +#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733 +#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000 +#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129 +#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785 +#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86 +#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072 +#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33 +#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161 +msgid "Cancel" +msgstr "Cancelar" + +#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94 +msgid "Tracks" +msgstr "Faixas" + +#: gtk_ardour/add_route_dialog.cc:43 +msgid "Busses" +msgstr "Barramentos" + +#: gtk_ardour/add_route_dialog.cc:48 +msgid "ardour: add track/bus" +msgstr "ardour: acrescentar faixa/barramento" + +#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81 +msgid "Add" +msgstr "Acrescentar" + +#: gtk_ardour/add_route_dialog.cc:86 +msgid "Name (template)" +msgstr "Nome (modelo)" + +#: gtk_ardour/ardour_ui.cc:798 +msgid "" +"pre\n" +"roll" +msgstr "" +"pré\n" +"batimento" + +#: gtk_ardour/ardour_ui.cc:799 +msgid "" +"post\n" +"roll" +msgstr "" +"pós\n" +"batimento" + +#: gtk_ardour/ardour_ui.cc:807 +msgid "% " +msgstr "" + +#: gtk_ardour/ardour_ui.cc:808 +msgid "spring" +msgstr "saltar" + +#: gtk_ardour/ardour_ui.cc:810 +msgid "" +"punch\n" +"in" +msgstr "" +"início de\n" +"inserção" + +#: gtk_ardour/ardour_ui.cc:811 +msgid "" +"punch\n" +"out" +msgstr "" +"final de\n" +"inserção" + +#: gtk_ardour/ardour_ui.cc:812 +msgid "" +"auto\n" +"return" +msgstr "" +"retorno\n" +"automático" + +#: gtk_ardour/ardour_ui.cc:813 +msgid "" +"auto\n" +"play" +msgstr "" +"reprodução\n" +"automática" + +#: gtk_ardour/ardour_ui.cc:814 +msgid "" +"auto\n" +"input" +msgstr "" +"entrada\n" +"automática" + +#: gtk_ardour/ardour_ui.cc:815 +msgid "click" +msgstr "Batimento" + +#: gtk_ardour/ardour_ui.cc:816 +msgid "" +"follow\n" +"PH" +msgstr "" +"acompanhar\n" +"c.reprod." + +#: gtk_ardour/ardour_ui.cc:817 +msgid "AUDITIONING" +msgstr "AUDIÇÃO" + +#: gtk_ardour/ardour_ui.cc:818 +msgid "SOLO" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:870 +msgid "Percentage" +msgstr "Percentagem" + +#: gtk_ardour/ardour_ui.cc:872 +msgid "Semitones" +msgstr "Semitons" + +#: gtk_ardour/ardour_ui.cc:875 +msgid "Sprung" +msgstr "Salto" + +#: gtk_ardour/ardour_ui.cc:877 +msgid "Wheel" +msgstr "Roda" + +#: gtk_ardour/ardour_ui.cc:902 +msgid "" +"You cannot record-enable\n" +"track %1\n" +"because it has no input connections.\n" +"You would be wasting space recording silence." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1073 +msgid "quit" +msgstr "sair" + +#: gtk_ardour/ardour_ui.cc:1082 +msgid "" +"Ardour was unable to save your session.\n" +"\n" +"If you still wish to quit, please use the\n" +"\n" +"\"Just quit\" option." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1107 +msgid "Save and %1" +msgstr "Guardar e %1" + +#: gtk_ardour/ardour_ui.cc:1112 +msgid "Just %1" +msgstr "Apenas %1" + +#: gtk_ardour/ardour_ui.cc:1117 +msgid "Don't %1" +msgstr "Não %1" + +#: gtk_ardour/ardour_ui.cc:1126 +#, fuzzy +msgid "session" +msgstr "Sessão" + +#: gtk_ardour/ardour_ui.cc:1128 +#, fuzzy +msgid "snapshot" +msgstr "Capturar" + +#: gtk_ardour/ardour_ui.cc:1130 +#, fuzzy +msgid "" +"The %1\n" +"\"%2\"\n" +"has not been saved.\n" +"\n" +"Any changes made this time\n" +"will be lost unless you save it.\n" +"\n" +"What do you want to do?" +msgstr "" +"A sessão \"%1\"\n" +"ainda não se encontra salvaguardada.\n" +"\n" +"Qualquer alteração feita até ao momento\n" +"ficará perdida se não a salvaguardar agora.\n" +"\n" +"O que pretende fazer?" + +#: gtk_ardour/ardour_ui.cc:1151 +msgid "Prompter" +msgstr "Alerta" + +#: gtk_ardour/ardour_ui.cc:1152 +msgid "ardour: save session?" +msgstr "ardour: guardar sessão?" + +#: gtk_ardour/ardour_ui.cc:1219 +#, fuzzy, c-format +msgid "disconnected" +msgstr "Desligar" + +#: gtk_ardour/ardour_ui.cc:1226 +#, fuzzy, c-format +msgid "SR: %.1f kHz / %4.1f msecs" +msgstr "FA: %.1f kHz" + +#: gtk_ardour/ardour_ui.cc:1230 +#, c-format +msgid "SR: %u kHz / %4.1f msecs" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1243 +#, c-format +msgid "DSP Load: %.1f%%" +msgstr "Carga DSP: %.1f%%" + +#: gtk_ardour/ardour_ui.cc:1253 +#, c-format +msgid "Disk r:%5.1f w:%5.1f MB/s" +msgstr "Disco r:%5.1f w:%5.1f MB/s" + +#: gtk_ardour/ardour_ui.cc:1267 +#, c-format +msgid "Buffers p:%%% c:%%%" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1294 +msgid "space: 24hrs+" +msgstr "espaço: 24hrs+" + +#: gtk_ardour/ardour_ui.cc:1324 +#, c-format +msgid "space: %02dh:%02dm:%02ds" +msgstr "espaço: %02dh:%02dm:%02ds" + +#: gtk_ardour/ardour_ui.cc:1575 +msgid "programming error: impossible control method" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1800 +msgid "cancel" +msgstr "cancelar" + +#: gtk_ardour/ardour_ui.cc:1801 +msgid "rescan" +msgstr "refrescar" + +#: gtk_ardour/ardour_ui.cc:1842 +msgid "open session" +msgstr "abrir sessão" + +#: gtk_ardour/ardour_ui.cc:1897 +msgid "Patience is a virtue.\n" +msgstr "A paciência é uma virtude.\n" + +#: gtk_ardour/ardour_ui.cc:1906 +msgid "You cannot add a track without a session already loaded." +msgstr "" +"Não é possível acrescentar uma faixa sem que haja uma sessão esteja " +"carregada." + +#: gtk_ardour/ardour_ui.cc:1913 +msgid "could not create new audio track" +msgstr "não foi possível criar uma nova faixa audio" + +#: gtk_ardour/ardour_ui.cc:1917 +msgid "could not create new audio bus" +msgstr "não foi possível criar um novo barramento audio" + +#: gtk_ardour/ardour_ui.cc:1936 +msgid "" +"There are insufficient JACK ports available\n" +"to create a new track or bus.\n" +"You should save Ardour, exit and\n" +"restart JACK with more ports." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2071 +msgid "" +"Please create 1 or more track\n" +"before trying to record.\n" +"Check the Session menu." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2312 +#, fuzzy +msgid "" +"JACK has either been shutdown or it\n" +"disconnected Ardour because Ardour\n" +"was not fast enough. You can save the\n" +"session and/or try to reconnect to JACK ." +msgstr "" +"O serviço de audio (JACK) foi desactivado ou\n" +"o mesmo desligou a sua ligação com o Ardour,\n" +"talvez porque este não o acompanhava suficientemente.\n" +"A sessão corrente deverá ser salvaguardada\n" +"e o serviço JACK reiniciado, tal como o Ardour." + +#: gtk_ardour/ardour_ui.cc:2328 +msgid "Unable to create all required ports" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2336 +#, fuzzy +msgid "Unable to start the session running" +msgstr "Ir para o início da sessão" + +#: gtk_ardour/ardour_ui.cc:2472 +msgid "No Stream" +msgstr "Sem Fluxo" + +#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518 +msgid "none" +msgstr "nenhum" + +#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527 +#: gtk_ardour/automation_time_axis.cc:189 +#: gtk_ardour/automation_time_axis.cc:218 +#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211 +#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947 +#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659 +msgid "off" +msgstr "desligado" + +#: gtk_ardour/ardour_ui.cc:2548 +msgid "Name for snapshot" +msgstr "Nome para a imagem capturada" + +#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294 +msgid "Name for mix template:" +msgstr "Nome para o modelo de mistura" + +#: gtk_ardour/ardour_ui.cc:2717 +msgid "-template" +msgstr "-modelo" + +#: gtk_ardour/ardour_ui.cc:2760 +msgid "Session %1 already exists at %2" +msgstr "Sessão %1 já existe em %2" + +#: gtk_ardour/ardour_ui.cc:2832 +msgid "" +"You do not have write access to this session.\n" +"This prevents the session from being loaded." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897 +msgid "Session \"%1 (snapshot %2)\" did not load successfully" +msgstr "Não foi possível carregar a sessão \"%1 (captura %2)\" com sucesso" + +#: gtk_ardour/ardour_ui.cc:2966 +msgid "" +"No audio files were ready for cleanup\n" +"\n" +"If this seems suprising, check for any existing\n" +"snapshots. These may still include regions that\n" +"require some unused files to continue to exist." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001 +msgid "files" +msgstr "ficheiros" + +#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003 +msgid "file" +msgstr "ficheiro" + +#: gtk_ardour/ardour_ui.cc:3026 +msgid "ardour: cleanup" +msgstr "ardour: limpeza" + +#: gtk_ardour/ardour_ui.cc:3040 +msgid "" +"Cleanup is a destructive operation.\n" +"ALL undo/redo information will be lost if you cleanup.\n" +"Unused audio files will be moved to a \"dead sounds\" location." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3045 +msgid "Proceed with cleanup" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3061 +#, fuzzy +msgid "CleanupDialog" +msgstr "Apagar" + +#: gtk_ardour/ardour_ui.cc:3062 +#, fuzzy +msgid "ardour cleanup" +msgstr "ardour: limpeza" + +#: gtk_ardour/ardour_ui.cc:3063 +#, fuzzy +msgid "ardour_cleanup" +msgstr "ardour: limpeza" + +#: gtk_ardour/ardour_ui.cc:3086 +msgid "cleaned files" +msgstr "ficheiros limpos" + +#: gtk_ardour/ardour_ui.cc:3087 +msgid "" +"The following %1 %2 were not in use.\n" +"The next time you flush the wastebasket\n" +"it will release an additional %3 %4bytes\n" +"of disk space" +msgstr "" +"Os seguintes %1 %2 não se encontram em uso.\n" +"Da próxima vez que efectuar uma limpeza\n" +"irão ser libertados %3 %4 de espaço em disco" + +#: gtk_ardour/ardour_ui.cc:3110 +msgid "deleted file" +msgstr "ficheiro eliminado" + +#: gtk_ardour/ardour_ui.cc:3111 +msgid "" +"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space" +msgstr "" +"Os seguintes %1 ficheiro%2 foram eliminados, libertando %3 %4B de espaço em " +"disco" + +#: gtk_ardour/ardour_ui.cc:3226 +msgid "Recording was stopped because your system could not keep up." +msgstr "" +"A gravação foi interrompida porque o seu sistema não foi capaz de a " +"acompanhar." + +#: gtk_ardour/ardour_ui.cc:3248 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to write data to disk\n" +"quickly enough to keep up with recording.\n" +msgstr "" +"O sistema de ficheiros em disco do seu computador\n" +"não foi capaz de manter o serviço audio do Ardour.\n" +"\n" +"Especificamente, a velocidade de escrita de dados em disco\n" +"foi insuficiente para acompanhar o ritmo de gravação.\n" + +#: gtk_ardour/ardour_ui.cc:3266 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to read data from disk\n" +"quickly enough to keep up with playback.\n" +msgstr "" +"O sistema de ficheiros em disco do seu computador\n" +"não foi capaz de manter o serviço audio do Ardour.\n" +"\n" +"Especificamente, a velocidade de leitura de dados em disco\n" +"foi insuficiente para acompanhar o ritmo de reprodução.\n" + +#: gtk_ardour/ardour_ui.cc:3291 +msgid "Recover from crash" +msgstr "Recuperação" + +#: gtk_ardour/ardour_ui.cc:3292 +msgid "Ignore crash data" +msgstr "Ignorar informação de recuperação" + +#: gtk_ardour/ardour_ui.cc:3293 +msgid "" +"This session appears to have been in\n" +"middle of recording when ardour or\n" +"the computer was shutdown.\n" +"\n" +"Ardour can recover any captured audio for\n" +"you, or it can ignore it. Please decide\n" +"what you would like to do.\n" +msgstr "" +"Esta sessão parece ter estado a meio\n" +"de uma gravação quando o Ardour ou\n" +"o computador foi desligado.\n" +"\n" +"Pode ser tentada a recuperação do audio\n" +"capturado até então ou simplesmente ignorá-lo.\n" +"Por favor decida o que pretende fazer.\n" + +#: gtk_ardour/ardour_ui.cc:3338 +#, fuzzy +msgid "Could not disconnect from JACK" +msgstr "Não foi possível conectar ao serviço JACK como \"%1\"" + +#: gtk_ardour/ardour_ui.cc:3351 +#, fuzzy +msgid "Could not reconnect to JACK" +msgstr "Não foi possível conectar ao serviço JACK como \"%1\"" + +#: gtk_ardour/ardour_ui2.cc:60 +msgid "UI: cannot setup editor" +msgstr "Não foi possível iniciar o painel principal de edição (editor)" + +#: gtk_ardour/ardour_ui2.cc:65 +msgid "UI: cannot setup mixer" +msgstr "Não foi posivel iniciar o painel de mistura" + +#: gtk_ardour/ardour_ui2.cc:70 +msgid "UI: cannot setup meter_bridge" +msgstr "Não foi possível iniciar o monitor volumétrico (vuímetro)" + +#: gtk_ardour/ardour_ui2.cc:98 +msgid "MMC + Local" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:99 +msgid "MMC" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:100 +msgid "Local" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:117 +msgid "MMC ID" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:215 +msgid "Play from playhead" +msgstr "Reproduzir desde o cursor de reprodução" + +#: gtk_ardour/ardour_ui2.cc:216 +msgid "Stop playback" +msgstr "Parar reprodução" + +#: gtk_ardour/ardour_ui2.cc:217 +msgid "Play range/selection" +msgstr "Reproduzir selecção" + +#: gtk_ardour/ardour_ui2.cc:218 +msgid "Go to start of session" +msgstr "Ir para o início da sessão" + +#: gtk_ardour/ardour_ui2.cc:219 +msgid "Go to end of session" +msgstr "Ir para o final da sessão" + +#: gtk_ardour/ardour_ui2.cc:220 +msgid "Play loop range" +msgstr "Reproduzir intervalo cíclico" + +#: gtk_ardour/ardour_ui2.cc:221 +msgid "Return to last playback start when stopped" +msgstr "Ir para a última posição inicial do cursor de reprodução quando parar" + +#: gtk_ardour/ardour_ui2.cc:222 +msgid "Start playback after any locate" +msgstr "Iniciar a reprodução após qualquer localização" + +#: gtk_ardour/ardour_ui2.cc:223 +msgid "Be sensible about input monitoring" +msgstr "Seja sensível acerca de monitorização de entradas" + +#: gtk_ardour/ardour_ui2.cc:224 +msgid "Start recording at auto-punch start" +msgstr "Iniciar gravação na posição inicial de inserção automática" + +#: gtk_ardour/ardour_ui2.cc:225 +msgid "Stop recording at auto-punch end" +msgstr "Parar gravação na posição final de inserção automática" + +#: gtk_ardour/ardour_ui2.cc:226 +msgid "Enable/Disable audio click" +msgstr "Ligar/Desligar o metrónomo" + +#: gtk_ardour/ardour_ui2.cc:227 +msgid "Enable/Disable follow playhead" +msgstr "Ligar/Desligar acompanhamento ao cursor de reprodução" + +#: gtk_ardour/ardour_ui2.cc:228 +msgid "Shuttle speed control" +msgstr "Controlo de velocidade" + +#: gtk_ardour/ardour_ui2.cc:229 +#, fuzzy, c-format +msgid "Select semitones or %%-age for speed display" +msgstr "Seleccionar semitons ou %-agem para visualização de velocidade" + +#: gtk_ardour/ardour_ui2.cc:230 +msgid "Select sprung or wheel behaviour" +msgstr "Seleccionar modo de salto ou de rolamento" + +#: gtk_ardour/ardour_ui2.cc:231 +msgid "Current transport speed" +msgstr "Velocidade de transporte actual" + +#: gtk_ardour/ardour_ui2.cc:312 +msgid "Primary clock" +msgstr "Cronómetro principal" + +#: gtk_ardour/ardour_ui2.cc:313 +msgid "secondary clock" +msgstr "Cronómetro secundário" + +#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751 +#: gtk_ardour/ardour_ui2.cc:770 +msgid "stopped" +msgstr "parado" + +#: gtk_ardour/ardour_ui2.cc:431 +msgid "ardour: clock" +msgstr "ardour: cronómetro" + +#: gtk_ardour/ardour_ui2.cc:721 +msgid "st" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:731 +msgid "sprung" +msgstr "mola" + +#: gtk_ardour/ardour_ui2.cc:742 +msgid "wheel" +msgstr "roda" + +#: gtk_ardour/ardour_ui_dependents.cc:74 +msgid "keyboard_target: error setting binding state: invalid node" +msgstr "" + +#: gtk_ardour/ardour_ui_dialogs.cc:158 +msgid "close session" +msgstr "fechar sessão" + +#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895 +msgid "New" +msgstr "Novo" + +#: gtk_ardour/ardour_ui_ed.cc:76 +msgid "Open" +msgstr "Abrir" + +#: gtk_ardour/ardour_ui_ed.cc:77 +msgid "Recent" +msgstr "Recente" + +#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +msgid "Close" +msgstr "Fechar" + +#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488 +msgid "Add Track/Bus" +msgstr "Acrescentar Faixa/Barramento" + +#: gtk_ardour/ardour_ui_ed.cc:99 +msgid "Connect" +msgstr "Ligar" + +#: gtk_ardour/ardour_ui_ed.cc:100 +msgid "Image Compositor" +msgstr "Compositor de Imagem" + +#: gtk_ardour/ardour_ui_ed.cc:114 +msgid "Save" +msgstr "Guardar" + +#: gtk_ardour/ardour_ui_ed.cc:118 +msgid "Snapshot" +msgstr "Capturar" + +#: gtk_ardour/ardour_ui_ed.cc:126 +msgid "Save Template..." +msgstr "Guardar Modelo..." + +#: gtk_ardour/ardour_ui_ed.cc:133 +msgid "Export session to audiofile..." +msgstr "Exportar sessão para ficheiro audio..." + +#: gtk_ardour/ardour_ui_ed.cc:134 +msgid "Export range to audiofile..." +msgstr "Exportar intervalo para ficheiro audio..." + +#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312 +#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118 +#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227 +msgid "Export" +msgstr "Exportar" + +#: gtk_ardour/ardour_ui_ed.cc:146 +msgid "Cleanup unused sources" +msgstr "Apagar originais em desuso" + +#: gtk_ardour/ardour_ui_ed.cc:147 +msgid "Flush wastebasket" +msgstr "Limpeza" + +#: gtk_ardour/ardour_ui_ed.cc:149 +msgid "Cleanup" +msgstr "Apagar" + +#: gtk_ardour/ardour_ui_ed.cc:154 +msgid "Quit" +msgstr "Sair" + +#: gtk_ardour/ardour_ui_ed.cc:156 +msgid "Session" +msgstr "Sessão" + +#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287 +#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499 +#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570 +#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412 +msgid "Edit" +msgstr "Editar" + +#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572 +#: gtk_ardour/mixer_strip.cc:631 +msgid "Disconnect" +msgstr "Desligar" + +#: gtk_ardour/ardour_ui_ed.cc:174 +#, fuzzy +msgid "Reconnect" +msgstr "Ligar" + +#: gtk_ardour/ardour_ui_ed.cc:192 +msgid "Latency" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:195 +#, fuzzy +msgid "JACK" +msgstr "RECUAR" + +#: gtk_ardour/ardour_ui_ed.cc:205 +msgid "Editor" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:206 +msgid "Mixer" +msgstr "Mistura" + +#: gtk_ardour/ardour_ui_ed.cc:212 +msgid "Options Editor" +msgstr "Opções" + +#: gtk_ardour/ardour_ui_ed.cc:219 +msgid "Audio Library" +msgstr "Audioteca" + +#: gtk_ardour/ardour_ui_ed.cc:225 +#, fuzzy +msgid "Track/Bus Inspector" +msgstr "Faixas/Barramentos" + +#: gtk_ardour/ardour_ui_ed.cc:232 +msgid "Connections" +msgstr "Ligações" + +#: gtk_ardour/ardour_ui_ed.cc:240 +msgid "Meter Bridge" +msgstr "VUímetro" + +#: gtk_ardour/ardour_ui_ed.cc:248 +msgid "Locations" +msgstr "Localizações" + +#: gtk_ardour/ardour_ui_ed.cc:255 +msgid "Big Clock" +msgstr "Cronómetro Principal" + +#: gtk_ardour/ardour_ui_ed.cc:261 +msgid "About" +msgstr "Acerca de" + +#: gtk_ardour/ardour_ui_ed.cc:264 +msgid "Windows" +msgstr "Janelas" + +#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203 +msgid "SMPTE" +msgstr "" + +#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202 +#: gtk_ardour/editor_rulers.cc:359 +msgid "Bars:Beats" +msgstr "Comp:Bat" + +#: gtk_ardour/audio_clock.cc:1642 +msgid "Minutes:Seconds" +msgstr "Mins:Segs" + +#: gtk_ardour/audio_clock.cc:1643 +msgid "Audio Frames" +msgstr "Quadros Audio" + +#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356 +#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713 +#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774 +#: gtk_ardour/option_editor.cc:794 +msgid "Off" +msgstr "Desligado" + +#: gtk_ardour/audio_clock.cc:1646 +msgid "Mode" +msgstr "Modo" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523 +msgid "m" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524 +msgid "s" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:104 +msgid "r" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:108 +msgid "g" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:109 +msgid "p" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44 +#: gtk_ardour/visual_time_axis.cc:90 +msgid "h" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:111 +msgid "a" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89 +msgid "v" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:185 +msgid "Record" +msgstr "Gravar" + +#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191 +msgid "Solo" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236 +#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433 +msgid "Mute" +msgstr "Mudo" + +#: gtk_ardour/audio_time_axis.cc:188 +msgid "Edit Group" +msgstr "Grupo" + +#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110 +msgid "Display Height" +msgstr "Altura" + +#: gtk_ardour/audio_time_axis.cc:190 +msgid "Playlist" +msgstr "Lista de Reprodução" + +#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752 +msgid "Automation" +msgstr "Automatização" + +#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111 +msgid "Visual options" +msgstr "Opções visuais" + +#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112 +msgid "Hide this track" +msgstr "Esconder esta faixa" + +#: gtk_ardour/audio_time_axis.cc:349 +msgid "No group" +msgstr "Sem grupo" + +#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447 +#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229 +msgid "Height" +msgstr "Altura" + +#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266 +#: gtk_ardour/marker_time_axis.cc:230 +msgid "Color" +msgstr "Cor" + +#: gtk_ardour/audio_time_axis.cc:720 +msgid "Hide all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:721 +msgid "Show all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:729 +msgid "show all automation" +msgstr "Mostrar todos as automatizações" + +#: gtk_ardour/audio_time_axis.cc:732 +msgid "show existing automation" +msgstr "Mostrar automatizações existentes" + +#: gtk_ardour/audio_time_axis.cc:735 +msgid "hide all automation" +msgstr "Esconder todos as automatizações" + +#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204 +#: gtk_ardour/editor.cc:234 +msgid "gain" +msgstr "ganho" + +#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244 +msgid "pan" +msgstr "pan" + +#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388 +msgid "Plugins" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95 +msgid "Show waveforms" +msgstr "Mostrar formas de onda" + +#: gtk_ardour/audio_time_axis.cc:766 +msgid "Traditional" +msgstr "Tradicional" + +#: gtk_ardour/audio_time_axis.cc:769 +msgid "Rectified" +msgstr "Rectificado" + +#: gtk_ardour/audio_time_axis.cc:772 +msgid "Waveform" +msgstr "Forma de onda" + +#: gtk_ardour/audio_time_axis.cc:782 +#, fuzzy +msgid "align with existing material" +msgstr "Material existente" + +#: gtk_ardour/audio_time_axis.cc:787 +#, fuzzy +msgid "align with capture time" +msgstr "Tempo de captura" + +#: gtk_ardour/audio_time_axis.cc:793 +#, fuzzy +msgid "Alignment" +msgstr "Alinhar" + +#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288 +msgid "Active" +msgstr "Activar" + +#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386 +#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467 +#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269 +#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233 +#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83 +msgid "Remove" +msgstr "Remover" + +#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880 +#: gtk_ardour/audio_time_axis.cc:911 +msgid "Name for playlist" +msgstr "Nome para lista de reprodução" + +#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433 +msgid "a track already exists with that name" +msgstr "já existe uma faixa com este nome" + +#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001 +#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539 +msgid "programming error: " +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:1889 +msgid "Current: %1" +msgstr "Actual: %1" + +#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452 +#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226 +#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377 +msgid "Rename" +msgstr "Renomear" + +#: gtk_ardour/audio_time_axis.cc:1896 +msgid "New Copy" +msgstr "Nova Cópia" + +#: gtk_ardour/audio_time_axis.cc:1898 +msgid "Clear Current" +msgstr "Limpar Actual" + +#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472 +#: gtk_ardour/editor.cc:2557 +msgid "Select" +msgstr "Seleccionar" + +#: gtk_ardour/automation_line.cc:904 +msgid "automation event move" +msgstr "mover evento de automatização" + +#: gtk_ardour/automation_line.cc:906 +msgid "automation range drag" +msgstr "deslocar intervalo de automatização" + +#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64 +msgid "remove control point" +msgstr "remover ponto de controlo" + +#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010 +msgid "clear" +msgstr "apagar" + +#: gtk_ardour/automation_time_axis.cc:80 +msgid "track height" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:81 +#, fuzzy +msgid "automation state" +msgstr "ponto de automatização de panorâmica" + +#: gtk_ardour/automation_time_axis.cc:82 +#, fuzzy +msgid "clear track" +msgstr "apagar intervalos" + +#: gtk_ardour/automation_time_axis.cc:83 +#, fuzzy +msgid "hide track" +msgstr "retocar faixa" + +#: gtk_ardour/automation_time_axis.cc:191 +#: gtk_ardour/automation_time_axis.cc:229 +#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213 +#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419 +#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50 +msgid "play" +msgstr "reproduzir" + +#: gtk_ardour/automation_time_axis.cc:193 +#: gtk_ardour/automation_time_axis.cc:240 +#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215 +#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422 +#: gtk_ardour/plugin_ui.cc:663 +msgid "write" +msgstr "escrita" + +#: gtk_ardour/automation_time_axis.cc:195 +#: gtk_ardour/automation_time_axis.cc:251 +#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217 +#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953 +#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665 +msgid "touch" +msgstr "tocar" + +#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274 +#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428 +msgid "???" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:276 +msgid "clear automation" +msgstr "apagar automatizações" + +#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453 +#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398 +msgid "Hide" +msgstr "Esconder" + +#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52 +#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364 +msgid "Clear" +msgstr "Apagar" + +#: gtk_ardour/automation_time_axis.cc:474 +#, fuzzy +msgid "State" +msgstr "Início" + +#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49 +msgid "Input Connections" +msgstr "Ligações de Entrada" + +#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48 +msgid "Output Connections" +msgstr "Ligações de Saída" + +#: gtk_ardour/connection_editor.cc:49 +#, fuzzy +msgid "New Input" +msgstr "nova entrada" + +#: gtk_ardour/connection_editor.cc:50 +#, fuzzy +msgid "New Output" +msgstr "nova saída" + +#: gtk_ardour/connection_editor.cc:51 +#, fuzzy +msgid "Delete" +msgstr "eliminar" + +#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96 +#, fuzzy +msgid "Add Port" +msgstr "acrescentar porta" + +#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105 +#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786 +#, fuzzy +msgid "Rescan" +msgstr "refrescar" + +#: gtk_ardour/connection_editor.cc:101 +msgid "Available Ports" +msgstr "Portas Disponíveis" + +#: gtk_ardour/connection_editor.cc:183 +msgid "ardour: connections" +msgstr "ardour: ligações" + +#: gtk_ardour/connection_editor.cc:513 +#, c-format +msgid "in %d" +msgstr "em %d" + +#: gtk_ardour/connection_editor.cc:644 +msgid "Name for new connection:" +msgstr "Nome para a nova ligação:" + +#: gtk_ardour/crossfade_edit.cc:71 +#, fuzzy +msgid "crossfade editor" +msgstr "alterar evanescimento" + +#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449 +#, fuzzy +msgid "Reset" +msgstr "reiniciar" + +#: gtk_ardour/crossfade_edit.cc:78 +#, fuzzy +msgid "Fade" +msgstr "Desvanecimentos" + +#: gtk_ardour/crossfade_edit.cc:79 +#, fuzzy +msgid "Out (dry)" +msgstr "saída (limpa)" + +#: gtk_ardour/crossfade_edit.cc:80 +#, fuzzy +msgid "Out" +msgstr "Saída" + +#: gtk_ardour/crossfade_edit.cc:81 +#, fuzzy +msgid "In (dry)" +msgstr "entrada (limpa)" + +#: gtk_ardour/crossfade_edit.cc:82 +msgid "In" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:84 +#, fuzzy +msgid "With Pre-roll" +msgstr "com pré-batimento" + +#: gtk_ardour/crossfade_edit.cc:85 +#, fuzzy +msgid "With Post-roll" +msgstr "com pós-batimento" + +#: gtk_ardour/crossfade_edit.cc:93 +msgid "Fade In" +msgstr "Evanescimento" + +#: gtk_ardour/crossfade_edit.cc:94 +msgid "Fade Out" +msgstr "Desvanecimento" + +#: gtk_ardour/crossfade_edit.cc:98 +msgid "ardour: x-fade edit" +msgstr "ardour: desvanecimento cruzado" + +#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311 +#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189 +msgid "Audition" +msgstr "Audição" + +#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804 +msgid "Regions/name" +msgstr "Regiões" + +#: gtk_ardour/editor.cc:108 +msgid "Chunks" +msgstr "Trechos" + +#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079 +msgid "Slide" +msgstr "Deslizar" + +#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077 +msgid "Splice" +msgstr "Reunir" + +#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136 +#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96 +#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977 +msgid "None" +msgstr "Nenhum" + +#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124 +msgid "CD Frames" +msgstr "Quadros CD" + +#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126 +msgid "SMPTE Frames" +msgstr "Quadros SMPTE" + +#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128 +msgid "SMPTE Seconds" +msgstr "Segundos SMPTE" + +#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130 +msgid "SMPTE Minutes" +msgstr "Minutos SMPTE" + +#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132 +msgid "Seconds" +msgstr "Segundos" + +#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134 +msgid "Minutes" +msgstr "Minutos" + +#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106 +msgid "Beats/32" +msgstr "Batimentos/32" + +#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104 +msgid "Beats/16" +msgstr "Batimentos/16" + +#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102 +msgid "Beats/8" +msgstr "Batimentos/8" + +#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100 +msgid "Beats/4" +msgstr "Batimentos/4" + +#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098 +msgid "Beats/3" +msgstr "Batimentos/3" + +#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108 +msgid "Beats" +msgstr "Batimentos" + +#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110 +msgid "Bars" +msgstr "Compassos" + +#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112 +msgid "Marks" +msgstr "Marcas" + +#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114 +#: gtk_ardour/editor.cc:4182 +msgid "Edit Cursor" +msgstr "Cursor de Edição" + +#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116 +msgid "Region starts" +msgstr "Inícios de região" + +#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118 +msgid "Region ends" +msgstr "Finais de região" + +#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122 +msgid "Region syncs" +msgstr "Sincronismos de região" + +#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120 +msgid "Region bounds" +msgstr "Extremos de região" + +#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153 +#: gtk_ardour/time_axis_view.cc:449 +msgid "Normal" +msgstr "Normal" + +#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155 +msgid "Magnetic" +msgstr "Magnético" + +#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174 +#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237 +msgid "Left" +msgstr "Esquerda" + +#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176 +#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238 +msgid "Right" +msgstr "Direita" + +#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178 +msgid "Center" +msgstr "Centro" + +#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180 +msgid "Playhead" +msgstr "Cursor de Reprodução" + +#: gtk_ardour/editor.cc:201 +msgid "Mins:Secs" +msgstr "Mins:Segs" + +#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353 +msgid "Frames" +msgstr "Quadros" + +#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373 +msgid "Tempo" +msgstr "" + +#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367 +msgid "Meter" +msgstr "VUímetro" + +#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379 +msgid "Location Markers" +msgstr "Localizações" + +#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385 +msgid "Range Markers" +msgstr "Intervalos" + +#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391 +msgid "Loop/Punch Ranges" +msgstr "Ciclos/Inserção" + +#: gtk_ardour/editor.cc:221 +msgid "" +"editor\n" +"mixer" +msgstr "" +"edição\n" +"mistura" + +#: gtk_ardour/editor.cc:232 +msgid "range" +msgstr "intervalo" + +#: gtk_ardour/editor.cc:233 +msgid "object" +msgstr "objecto" + +#: gtk_ardour/editor.cc:235 +msgid "zoom" +msgstr "" + +#: gtk_ardour/editor.cc:236 +msgid "timefx" +msgstr "" + +#: gtk_ardour/editor.cc:237 +msgid "listen" +msgstr "" + +#: gtk_ardour/editor.cc:239 +msgid "mode" +msgstr "modo" + +#: gtk_ardour/editor.cc:240 +msgid "automation" +msgstr "automatização" + +#: gtk_ardour/editor.cc:242 +msgid "Edit Mode" +msgstr "Modo de Edição" + +#: gtk_ardour/editor.cc:243 +msgid "Snap To" +msgstr "Ajustar a" + +#: gtk_ardour/editor.cc:244 +msgid "Snap Mode" +msgstr "Modo de Ajuste" + +#: gtk_ardour/editor.cc:245 +msgid "Zoom Focus" +msgstr "Zoom(focagem)" + +#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364 +#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579 +msgid "Nudge" +msgstr "Retocar" + +#: gtk_ardour/editor.cc:511 +msgid "Zoom in" +msgstr "Zoom(+)" + +#: gtk_ardour/editor.cc:512 +msgid "Zoom out" +msgstr "Zoom(-)" + +#: gtk_ardour/editor.cc:517 +msgid "Zoom to session" +msgstr "Zoom(sessão)" + +#: gtk_ardour/editor.cc:536 +msgid "Zoom Span" +msgstr "Zoom(alcance)" + +#: gtk_ardour/editor.cc:566 +msgid "Edit Groups" +msgstr "Grupos" + +#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142 +msgid "-all-" +msgstr "-tudo-" + +#: gtk_ardour/editor.cc:718 +msgid "Nudge region/selection forwards" +msgstr "Retocar região/selecção para a frente" + +#: gtk_ardour/editor.cc:719 +msgid "Nudge region/selection backwards" +msgstr "Retocar região/selecção para trás" + +#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308 +msgid "ardour: editor" +msgstr "" + +#: gtk_ardour/editor.cc:729 +msgid "ardour_editor" +msgstr "" + +#: gtk_ardour/editor.cc:846 +msgid "VerboseCanvasCursor" +msgstr "" + +#: gtk_ardour/editor.cc:1405 +msgid "FirstActionMessage" +msgstr "" + +#: gtk_ardour/editor.cc:1407 +msgid "Start a new session\n" +msgstr "Iniciar uma nova sessão\n" + +#: gtk_ardour/editor.cc:1408 +msgid "via Session menu" +msgstr "via menu de Sessão" + +#: gtk_ardour/editor.cc:1703 +msgid "ardour: editor: " +msgstr "" + +#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796 +#: gtk_ardour/editor_markers.cc:797 +msgid "Loop" +msgstr "Ciclo" + +#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810 +#: gtk_ardour/editor_markers.cc:823 +msgid "Punch" +msgstr "Inserção" + +#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688 +msgid "programming error: fade in canvas item has no regionview data pointer!" +msgstr "" + +#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986 +#: gtk_ardour/redirect_box.cc:401 +msgid "Deactivate" +msgstr "Desactivar" + +#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988 +#: gtk_ardour/redirect_box.cc:398 +msgid "Activate" +msgstr "Activar" + +#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993 +msgid "Linear" +msgstr "" + +#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994 +#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734 +#: gtk_ardour/option_editor.cc:796 +msgid "Slowest" +msgstr "Mais lento" + +#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995 +#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735 +#: gtk_ardour/option_editor.cc:798 +msgid "Slow" +msgstr "Lento" + +#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996 +#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737 +#: gtk_ardour/option_editor.cc:802 +msgid "Fast" +msgstr "Rápido" + +#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997 +#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739 +#: gtk_ardour/option_editor.cc:806 +msgid "Fastest" +msgstr "Mais Rápido" + +#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113 +msgid "Freeze" +msgstr "Congelar" + +#: gtk_ardour/editor.cc:2109 +msgid "Unfreeze" +msgstr "Descongelar" + +#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328 +#, fuzzy +msgid "Unmute" +msgstr "mudo" + +#: gtk_ardour/editor.cc:2247 +msgid "Convert to short" +msgstr "" + +#: gtk_ardour/editor.cc:2249 +msgid "Convert to full" +msgstr "" + +#: gtk_ardour/editor.cc:2260 +#, fuzzy +msgid "Crossfade" +msgstr "Desvanecimento cruzado" + +#: gtk_ardour/editor.cc:2303 +msgid "Popup region editor" +msgstr "Editor de região" + +#: gtk_ardour/editor.cc:2304 +#, fuzzy +msgid "Raise to top layer" +msgstr "Elevar a região para o nível de topo" + +#: gtk_ardour/editor.cc:2305 +#, fuzzy +msgid "Lower to bottom layer" +msgstr "Descer a região para o nível de fundo" + +#: gtk_ardour/editor.cc:2307 +msgid "Define sync point" +msgstr "Definir ponto de sincronia" + +#: gtk_ardour/editor.cc:2308 +msgid "Remove sync point" +msgstr "Remover ponto de sincronia" + +#: gtk_ardour/editor.cc:2313 +#, fuzzy +msgid "Bounce" +msgstr "Rebater intervalo" + +#: gtk_ardour/editor.cc:2323 +msgid "Lock" +msgstr "Bloquear" + +#: gtk_ardour/editor.cc:2324 +msgid "Unlock" +msgstr "Desbloquear" + +#: gtk_ardour/editor.cc:2334 +msgid "Original position" +msgstr "Posição original" + +#: gtk_ardour/editor.cc:2340 +msgid "Toggle envelope visibility" +msgstr "" + +#: gtk_ardour/editor.cc:2341 +#, fuzzy +msgid "Toggle envelope active" +msgstr "Activação" + +#: gtk_ardour/editor.cc:2345 +msgid "DeNormalize" +msgstr "Denormalizar" + +#: gtk_ardour/editor.cc:2347 +msgid "Normalize" +msgstr "Normalizar" + +#: gtk_ardour/editor.cc:2350 +msgid "Reverse" +msgstr "Inverter" + +#: gtk_ardour/editor.cc:2359 +msgid "Nudge fwd" +msgstr "Retocar p/frente" + +#: gtk_ardour/editor.cc:2360 +msgid "Nudge bwd" +msgstr "Retocar p/trás" + +#: gtk_ardour/editor.cc:2361 +msgid "Nudge fwd by capture offset" +msgstr "Retocar p/frente captura" + +#: gtk_ardour/editor.cc:2362 +msgid "Nudge bwd by capture offset" +msgstr "Retocar p/trás captura" + +#: gtk_ardour/editor.cc:2371 +msgid "Start to edit cursor" +msgstr "Do início ao cursor de edição" + +#: gtk_ardour/editor.cc:2372 +msgid "Edit cursor to end" +msgstr "Do cursor de edição ao final" + +#: gtk_ardour/editor.cc:2374 +msgid "Trim" +msgstr "Cortar" + +#: gtk_ardour/editor.cc:2377 +msgid "Split" +msgstr "Separar" + +#: gtk_ardour/editor.cc:2380 +msgid "Make mono regions" +msgstr "Criar regiões mono" + +#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428 +msgid "Duplicate" +msgstr "Duplicar" + +#: gtk_ardour/editor.cc:2384 +msgid "Fill Track" +msgstr "Preencher Faixa" + +#: gtk_ardour/editor.cc:2388 +msgid "Destroy" +msgstr "Destruir" + +#: gtk_ardour/editor.cc:2418 +msgid "Play range" +msgstr "Reproduzir intervalo" + +#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446 +msgid "Loop range" +msgstr "Intervalo cíclico" + +#: gtk_ardour/editor.cc:2421 +msgid "Create chunk from range" +msgstr "Criar trecho desde intervalo" + +#: gtk_ardour/editor.cc:2423 +msgid "Create Region" +msgstr "Criar Região" + +#: gtk_ardour/editor.cc:2424 +msgid "Separate Region" +msgstr "Separar Região" + +#: gtk_ardour/editor.cc:2425 +msgid "Crop Region to range" +msgstr "Cortar Regão para intervalo" + +#: gtk_ardour/editor.cc:2426 +msgid "Bounce range" +msgstr "Rebater intervalo" + +#: gtk_ardour/editor.cc:2432 +msgid "Fill range w/Region" +msgstr "Preencher intervalo c/Região" + +#: gtk_ardour/editor.cc:2434 +msgid "Range" +msgstr "Intervalo" + +#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538 +msgid "Play from edit cursor" +msgstr "Reproduzir desde o cursor de edição" + +#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539 +msgid "Play from start" +msgstr "Reproduzir desde o início" + +#: gtk_ardour/editor.cc:2451 +#, fuzzy +msgid "Play region" +msgstr "Reproduzir Região" + +#: gtk_ardour/editor.cc:2453 +msgid "Loop Region" +msgstr "Região Cíclica" + +#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540 +#: gtk_ardour/library_ui.cc:972 +msgid "Play" +msgstr "Reproduzir" + +#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548 +msgid "Select All in track" +msgstr "Seleccionar tudo na faixa" + +#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549 +msgid "Select All" +msgstr "Seleccionar tudo" + +#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550 +msgid "Invert in track" +msgstr "Inverter na faixa" + +#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551 +msgid "Invert" +msgstr "Inverter" + +#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553 +msgid "Select loop range" +msgstr "Seleccionar intervalo de ciclo" + +#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554 +msgid "Select punch range" +msgstr "Seleccionar intervalo de inserção" + +#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565 +#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369 +msgid "Cut" +msgstr "Cortar" + +#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566 +#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371 +msgid "Copy" +msgstr "Copiar" + +#: gtk_ardour/editor.cc:2482 +#, fuzzy +msgid "Paste at edit cursor" +msgstr "Do início ao cursor de edição" + +#: gtk_ardour/editor.cc:2483 +#, fuzzy +msgid "Paste at mouse" +msgstr "usar saídas principais" + +#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923 +msgid "Align" +msgstr "Alinhar" + +#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925 +msgid "Align Relative" +msgstr "Alinhar Relativamente" + +#: gtk_ardour/editor.cc:2492 +msgid "Insert chunk" +msgstr "Inserir trecho" + +#: gtk_ardour/editor.cc:2496 +#, fuzzy +msgid "New Region from range" +msgstr "Nova região desde a selecção" + +#: gtk_ardour/editor.cc:2497 +msgid "Separate Range" +msgstr "Separar Intervalo" + +#: gtk_ardour/editor.cc:2507 +msgid "Insert Region" +msgstr "Inserir Região" + +#: gtk_ardour/editor.cc:2508 +msgid "Insert external sndfile" +msgstr "Inserir ficheiro audio externo" + +#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438 +msgid "Import" +msgstr "Importar" + +#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574 +msgid "Nudge entire track fwd" +msgstr "Retocar toda a faixa p/frente" + +#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575 +msgid "Nudge track after edit cursor fwd" +msgstr "Retocar a faixa p/frente do cursor de edição" + +#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576 +msgid "Nudge entire track bwd" +msgstr "Retocar toda a faixa p/trás" + +#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577 +msgid "Nudge track after edit cursor bwd" +msgstr "Retocar a faixa p/trás do cursor de edição" + +#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920 +#: gtk_ardour/redirect_box.cc:373 +msgid "Paste" +msgstr "Colar" + +#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645 +#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799 +msgid "add marker" +msgstr "adicionar marcador" + +#: gtk_ardour/editor.cc:3084 +msgid "select/move objects" +msgstr "seleccionar/mover objectos" + +#: gtk_ardour/editor.cc:3085 +msgid "select/move ranges" +msgstr "seleccionar/mover intervalos" + +#: gtk_ardour/editor.cc:3086 +msgid "draw gain automation" +msgstr "desenhar automatização de ganho" + +#: gtk_ardour/editor.cc:3087 +msgid "select zoom range" +msgstr "seleccionar zoom" + +#: gtk_ardour/editor.cc:3088 +msgid "stretch/shrink regions" +msgstr "alongar/estreitar regiões" + +#: gtk_ardour/editor.cc:3089 +#, fuzzy +msgid "listen to specific regions" +msgstr "seleccionar regiões" + +#: gtk_ardour/editor.cc:3213 +msgid "Start:" +msgstr "Início:" + +#: gtk_ardour/editor.cc:3214 +msgid "End:" +msgstr "Final:" + +#: gtk_ardour/editor.cc:3215 +msgid "Edit:" +msgstr "Editar:" + +#: gtk_ardour/editor.cc:3429 +msgid "incorrectly formatted URI list, ignored" +msgstr "lista de URIs mal formada, ignorada" + +#: gtk_ardour/editor.cc:3611 +#, fuzzy +msgid "set selected trackview" +msgstr "seleccionar visualização de faixa" + +#: gtk_ardour/editor.cc:3647 +#, fuzzy +msgid "set selected control point" +msgstr "remover ponto de controlo" + +#: gtk_ardour/editor.cc:3719 +msgid "set selected regionview" +msgstr "seleccionar visualização de região" + +#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835 +msgid "set selected regions" +msgstr "seleccionar regiões" + +#: gtk_ardour/editor.cc:3891 +msgid "Undo" +msgstr "Desfazer" + +#: gtk_ardour/editor.cc:3893 +msgid "Undo (%1)" +msgstr "Desfazer (%1)" + +#: gtk_ardour/editor.cc:3903 +msgid "Redo" +msgstr "Refazer" + +#: gtk_ardour/editor.cc:3905 +msgid "Redo (%1)" +msgstr "Refazer (%1)" + +#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946 +msgid "... as new track" +msgstr "" + +#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947 +#, fuzzy +msgid "... as new region" +msgstr "alinhar região" + +#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452 +msgid "Import audio (copy)" +msgstr "Importar audio (copiar)" + +#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457 +msgid "Embed audio (link)" +msgstr "Intercalar audio (ligar)" + +#: gtk_ardour/editor.cc:3953 +msgid "Remove last capture" +msgstr "Remover a última captura" + +#: gtk_ardour/editor.cc:3974 +msgid "Duplicate how many times?" +msgstr "Duplicar quantas vezes?" + +#: gtk_ardour/editor.cc:4550 +msgid "" +"Playlist %1 is currently unused.\n" +"If left alone, no audio files used by it will be cleaned.\n" +"If deleted, audio files used by it alone by will cleaned." +msgstr "" +"A lista de reprodução %1 não se encontra actualmente em uso.\n" +"Se for mantida assim, não serão elimnados os ficheiros de audio por ela " +"empregues.\n" +"Se for eliminada, todos os ficheiros de audio serão respectivamente " +"eliminados." + +#: gtk_ardour/editor.cc:4555 +msgid "Delete playlist" +msgstr "Eliminar lista de reprodução" + +#: gtk_ardour/editor.cc:4556 +#, fuzzy +msgid "Keep playlist" +msgstr "Manter lista de reprodução" + +#: gtk_ardour/editor.cc:4557 +msgid "Cancel cleanup" +msgstr "Cancelar eliminação" + +#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258 +#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290 +msgid "" +"programming error: control point canvas item has no control point object " +"pointer!" +msgstr "" + +#: gtk_ardour/editor_canvas_events.cc:717 +msgid "programming error: line canvas item has no line object pointer!" +msgstr "" + +#: gtk_ardour/editor_canvas_events.cc:744 +#: gtk_ardour/editor_canvas_events.cc:784 +#: gtk_ardour/editor_canvas_events.cc:823 +msgid "programming error: no \"rect\" pointer associated with selection item" +msgstr "" + +#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298 +#: gtk_ardour/mixer_ui.cc:670 +msgid "Show All" +msgstr "Mostrar tudo" + +#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299 +#: gtk_ardour/mixer_ui.cc:671 +msgid "Hide All" +msgstr "Ocultar tudo" + +#: gtk_ardour/editor_edit_groups.cc:98 +msgid "Name for new edit group" +msgstr "Nome para o novo grupo de edição" + +#: gtk_ardour/editor_export_audio.cc:60 +msgid "" +"There is no range to export.\n" +"\n" +"Select a range using the range mouse mode" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707 +msgid "programming error: no ImageFrameView selected" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930 +msgid "programming error: no MarkerView selected" +msgstr "" + +#: gtk_ardour/editor_keys.cc:187 +#, fuzzy +msgid "keyboard selection" +msgstr "extender selecção" + +#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376 +#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526 +#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584 +#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650 +#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700 +#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960 +#: gtk_ardour/editor_mouse.cc:4075 +msgid "programming error: marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681 +msgid "remove marker" +msgstr "remover marcador" + +#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494 +msgid "Locate to" +msgstr "Localizar" + +#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495 +msgid "Play from" +msgstr "Reproduzir desde" + +#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496 +msgid "Set from playhead" +msgstr "Desde cursor de reprodução" + +#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497 +msgid "Set from range" +msgstr "Seleccionar intervalo" + +#: gtk_ardour/editor_markers.cc:479 +msgid "Set Loop Range" +msgstr "Seleccionar Intervalo Cíclico" + +#: gtk_ardour/editor_markers.cc:480 +msgid "Set Punch Range" +msgstr "Seleccionar Intervalo de Inserção" + +#: gtk_ardour/editor_markers.cc:736 +msgid "ardour: rename mark" +msgstr "ardour: renomear marca" + +#: gtk_ardour/editor_markers.cc:738 +#, fuzzy +msgid "ardour: rename range" +msgstr "ardour: renomear região" + +#: gtk_ardour/editor_markers.cc:792 +msgid "set loop range" +msgstr "seleccionar intervalo cíclico" + +#: gtk_ardour/editor_markers.cc:818 +msgid "set punch range" +msgstr "seleccionar intervalo de inserção" + +#: gtk_ardour/editor_mouse.cc:99 +msgid "Editor::event_frame() used on unhandled event type %1" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1555 +msgid "programming error: start_grab called without drag item" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1760 +msgid "change fade in length" +msgstr "alterar duração de evanescimento" + +#: gtk_ardour/editor_mouse.cc:1778 +msgid "programming error: fade out canvas item has no regionview data pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:1852 +msgid "change fade out length" +msgstr "alterar duração desvanecimento" + +#: gtk_ardour/editor_mouse.cc:1871 +msgid "programming error: cursor canvas item has no cursor data pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470 +msgid "" +"programming error: meter marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2163 +msgid "move meter mark" +msgstr "remover marcador métrico" + +#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335 +#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439 +msgid "" +"programming error: tempo marker canvas item has no marker object pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340 +#: gtk_ardour/editor_tempodisplay.cc:425 +msgid "programming error: marker for tempo is not a tempo marker!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2245 +msgid "move tempo mark" +msgstr "remover marcador de tempo" + +#: gtk_ardour/editor_mouse.cc:2388 +msgid "programming error: line canvas item has no line pointer!" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2497 +#, fuzzy +msgid "move region(s)" +msgstr "remover região" + +#: gtk_ardour/editor_mouse.cc:2509 +msgid "Drag region copy" +msgstr "Arraster cópia de região" + +#: gtk_ardour/editor_mouse.cc:2579 +#, fuzzy +msgid "copy region(s)" +msgstr "Arrastar regiões" + +#: gtk_ardour/editor_mouse.cc:2612 +#, fuzzy +msgid "Drag region brush" +msgstr "Arrastar regiões" + +#: gtk_ardour/editor_mouse.cc:3425 +msgid "selection grab" +msgstr "selecção" + +#: gtk_ardour/editor_mouse.cc:3571 +msgid "range selection" +msgstr "selecção de intervalo" + +#: gtk_ardour/editor_mouse.cc:3587 +msgid "trim selection start" +msgstr "recortar início da selecção" + +#: gtk_ardour/editor_mouse.cc:3603 +msgid "trim selection end" +msgstr "recortar final da selecção" + +#: gtk_ardour/editor_mouse.cc:3620 +msgid "move selection" +msgstr "mover selecção" + +#: gtk_ardour/editor_mouse.cc:3995 +msgid "Start point trim" +msgstr "Ponto inicial de recorte" + +#: gtk_ardour/editor_mouse.cc:4023 +msgid "End point trim" +msgstr "Ponto final de recorte" + +#: gtk_ardour/editor_mouse.cc:4062 +msgid "trimmed region" +msgstr "região recortada" + +#: gtk_ardour/editor_mouse.cc:4203 +msgid "new range marker" +msgstr "novo marcador de região" + +#: gtk_ardour/editor_mouse.cc:4422 +msgid "select regions" +msgstr "seleccionar regiões" + +#: gtk_ardour/editor_mouse.cc:4451 +msgid "Name for region:" +msgstr "Nome para a região:" + +#: gtk_ardour/editor_mouse.cc:4517 +msgid "timestretch" +msgstr "alongamento temporal" + +#: gtk_ardour/editor_ops.cc:117 +msgid "split" +msgstr "separar" + +#: gtk_ardour/editor_ops.cc:153 +msgid "remove region" +msgstr "remover região" + +#: gtk_ardour/editor_ops.cc:172 +msgid "" +" This is destructive, will possibly delete audio files\n" +"It cannot be undone\n" +"Do you really want to destroy %1 ?" +msgstr "" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "these regions" +msgstr "inverter regiões" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "this region" +msgstr "emudecer esta região" + +#: gtk_ardour/editor_ops.cc:179 +#, fuzzy +msgid "Yes, destroy them." +msgstr "Sim, elimine-se." + +#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434 +msgid "Yes, destroy it." +msgstr "Sim, elimine-se." + +#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435 +#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300 +msgid "No, do nothing." +msgstr "Não, não fazer nada." + +#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307 +msgid "extend selection" +msgstr "extender selecção" + +#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357 +#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427 +msgid "nudge forward" +msgstr "retocar p/frente" + +#: gtk_ardour/editor_ops.cc:491 +msgid "build_region_boundary_cache called with snap_type = %1" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1305 +#, fuzzy +msgid "set selection from range" +msgstr "selecção de intervalo" + +#: gtk_ardour/editor_ops.cc:1421 +msgid "clear markers" +msgstr "apagar marcadores" + +#: gtk_ardour/editor_ops.cc:1433 +msgid "clear ranges" +msgstr "apagar intervalos" + +#: gtk_ardour/editor_ops.cc:1452 +msgid "clear locations" +msgstr "apagar localizações" + +#: gtk_ardour/editor_ops.cc:1503 +msgid "insert dragged region" +msgstr "inserir região arrastada" + +#: gtk_ardour/editor_ops.cc:1538 +msgid "insert region" +msgstr "inserir região" + +#: gtk_ardour/editor_ops.cc:1744 +msgid "ardour: rename region" +msgstr "ardour: renomear região" + +#: gtk_ardour/editor_ops.cc:1891 +msgid "You can't import an audiofile until you have a session loaded." +msgstr "" +"Não é possível importar um ficheiro audio sem que haja uma sessão carregada" + +#: gtk_ardour/editor_ops.cc:1901 +#, fuzzy +msgid "Import selected as tracks" +msgstr "Importar selecção" + +#: gtk_ardour/editor_ops.cc:1904 +#, fuzzy +msgid "Import selected to region list" +msgstr "seleccionar regiões" + +#: gtk_ardour/editor_ops.cc:1933 +msgid "ardour: audio import in progress" +msgstr "ardour: importação audio em curso" + +#: gtk_ardour/editor_ops.cc:1937 +msgid "Cancel Import" +msgstr "Cancelar Importação" + +#: gtk_ardour/editor_ops.cc:1944 +msgid "ardour: importing %1" +msgstr "ardour: em importação %1" + +#: gtk_ardour/editor_ops.cc:1990 +msgid "%1 it anyway" +msgstr "%s de qualquer forma" + +#: gtk_ardour/editor_ops.cc:1996 +#, fuzzy +msgid "Don't %1 it" +msgstr "Não %1" + +#: gtk_ardour/editor_ops.cc:1997 +msgid "%1 all without questions" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1998 +#, fuzzy +msgid "Cancel entire import" +msgstr "Cancelar Importação" + +#: gtk_ardour/editor_ops.cc:2004 +#, fuzzy +msgid "" +"%1\n" +"This audiofile's sample rate doesn't match the session sample rate!" +msgstr "" +"A frequência de amostragem deste ficheiro audio não é igual à de sessão" + +#: gtk_ardour/editor_ops.cc:2032 +msgid "You can't embed an audiofile until you have a session loaded." +msgstr "" +"Não é possível intercalar um ficheiro audio sem que haja uma sessão carregada" + +#: gtk_ardour/editor_ops.cc:2039 +msgid "Add to External Region list" +msgstr "Acrescentar à lista de Regiões Externas" + +#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210 +#: gtk_ardour/editor_ops.cc:2286 +msgid "Editor: cannot open file \"%1\" (%2)" +msgstr "Editor: não foi possível abrir o ficheiro \"%1\" (%2)" + +#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312 +msgid "could not open %1" +msgstr "não foi possível abrir %1" + +#: gtk_ardour/editor_ops.cc:2171 +#, fuzzy +msgid "Insert selected as new tracks" +msgstr "seleccionar visualização de faixa" + +#: gtk_ardour/editor_ops.cc:2186 +msgid "Insert selected" +msgstr "Inserir selecção" + +#: gtk_ardour/editor_ops.cc:2327 +msgid "insert sndfile" +msgstr "inserir ficheiro audio" + +#: gtk_ardour/editor_ops.cc:2464 +#, fuzzy +msgid "separate" +msgstr "separar" + +#: gtk_ardour/editor_ops.cc:2528 +msgid "trim to selection" +msgstr "recortar pela selecção" + +#: gtk_ardour/editor_ops.cc:2568 +msgid "region fill" +msgstr "preencher região" + +#: gtk_ardour/editor_ops.cc:2626 +msgid "fill selection" +msgstr "preencher selecção" + +#: gtk_ardour/editor_ops.cc:2650 +msgid "Place the edit cursor at the desired sync point" +msgstr "Coloque o cursor de edição sobre o ponto de sincronia desejado" + +#: gtk_ardour/editor_ops.cc:2656 +#, fuzzy +msgid "set sync from edit cursor" +msgstr "sincronizar pelo cursor de edição" + +#: gtk_ardour/editor_ops.cc:2668 +msgid "remove sync" +msgstr "remover sincronismo" + +#: gtk_ardour/editor_ops.cc:2682 +msgid "naturalize" +msgstr "naturalizar" + +#: gtk_ardour/editor_ops.cc:2746 +msgid "align selection (relative)" +msgstr "alinhar selecção (relativamente)" + +#: gtk_ardour/editor_ops.cc:2774 +msgid "align selection" +msgstr "alinhar selecção" + +#: gtk_ardour/editor_ops.cc:2786 +msgid "align region" +msgstr "alinhar região" + +#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858 +msgid "trim to edit" +msgstr "recortar para edição" + +#: gtk_ardour/editor_ops.cc:2909 +#, fuzzy +msgid "ardour: freeze" +msgstr "ardour: renomear região" + +#: gtk_ardour/editor_ops.cc:2914 +#, fuzzy +msgid "Cancel Freeze" +msgstr "Cancelar" + +#: gtk_ardour/editor_ops.cc:2951 +msgid "bounce range" +msgstr "intervalo de rebatimento" + +#: gtk_ardour/editor_ops.cc:3004 +msgid "cut" +msgstr "corte" + +#: gtk_ardour/editor_ops.cc:3007 +msgid "copy" +msgstr "cópia" + +#: gtk_ardour/editor_ops.cc:3020 +msgid " objects" +msgstr " objectos" + +#: gtk_ardour/editor_ops.cc:3046 +msgid " range" +msgstr " intervalo" + +#: gtk_ardour/editor_ops.cc:3201 +msgid "paste" +msgstr "colar" + +#: gtk_ardour/editor_ops.cc:3236 +msgid "paste chunk" +msgstr "colar trecho" + +#: gtk_ardour/editor_ops.cc:3276 +msgid "duplicate region" +msgstr "duplicar região" + +#: gtk_ardour/editor_ops.cc:3309 +msgid "duplicate selection" +msgstr "duplicar selecção" + +#: gtk_ardour/editor_ops.cc:3349 +msgid "clear playlist" +msgstr "limpar lista de reprodução" + +#: gtk_ardour/editor_ops.cc:3378 +msgid "nudge track" +msgstr "retocar faixa" + +#: gtk_ardour/editor_ops.cc:3431 +msgid "" +"Do you really want to destroy the last capture?\n" +"(This is destructive and cannot be undone)" +msgstr "" +"Deseja realmente eliminar a última captura?\n" +"(esta operação é destrutiva e não pode ser desfeita)" + +#: gtk_ardour/editor_ops.cc:3463 +msgid "normalize" +msgstr "normalizar" + +#: gtk_ardour/editor_ops.cc:3510 +msgid "reverse regions" +msgstr "inverter regiões" + +#: gtk_ardour/editor_region_list.cc:223 +msgid "hidden" +msgstr "esconder" + +#: gtk_ardour/editor_region_list.cc:408 +msgid "Show all" +msgstr "Mostrar tudo" + +#: gtk_ardour/editor_region_list.cc:417 +msgid "Ascending" +msgstr "Crescente" + +#: gtk_ardour/editor_region_list.cc:419 +msgid "Descending" +msgstr "Decrescente" + +#: gtk_ardour/editor_region_list.cc:423 +msgid "By Region Name" +msgstr "Por Nome de Região" + +#: gtk_ardour/editor_region_list.cc:425 +msgid "By Region Length" +msgstr "Por Tamanho de Região" + +#: gtk_ardour/editor_region_list.cc:427 +msgid "By Region Position" +msgstr "Por Posição de Região" + +#: gtk_ardour/editor_region_list.cc:429 +msgid "By Region Timestamp" +msgstr "Por Instante de Região" + +#: gtk_ardour/editor_region_list.cc:431 +msgid "By Region Start in File" +msgstr "Por Posição Inicial da Região no Ficheiro" + +#: gtk_ardour/editor_region_list.cc:433 +msgid "By Region End in File" +msgstr "Por Posição Final da Região no Ficheiro" + +#: gtk_ardour/editor_region_list.cc:435 +msgid "By Source File Name" +msgstr "Por Nome do Ficheiro Original" + +#: gtk_ardour/editor_region_list.cc:437 +msgid "By Source File Length" +msgstr "Por Tamanho do Ficheiro Original" + +#: gtk_ardour/editor_region_list.cc:439 +msgid "By Source File Creation Date" +msgstr "Por Data de Criação do Ficheiro Original" + +#: gtk_ardour/editor_region_list.cc:441 +msgid "By Source Filesystem" +msgstr "Por Sistema de Ficheiros Original" + +#: gtk_ardour/editor_region_list.cc:444 +msgid "Sorting" +msgstr "Ordenação" + +#: gtk_ardour/editor_region_list.cc:808 +msgid "Regions/length" +msgstr "Regiões/tamanho" + +#: gtk_ardour/editor_region_list.cc:812 +msgid "Regions/position" +msgstr "Regiões/posição" + +#: gtk_ardour/editor_region_list.cc:816 +msgid "Regions/creation" +msgstr "Regiões/criação" + +#: gtk_ardour/editor_region_list.cc:820 +msgid "Regions/start" +msgstr "Regiões/início" + +#: gtk_ardour/editor_region_list.cc:824 +msgid "Regions/end" +msgstr "Regiões/final" + +#: gtk_ardour/editor_region_list.cc:828 +msgid "Regions/file name" +msgstr "Regiões/nome de ficheiro" + +#: gtk_ardour/editor_region_list.cc:832 +msgid "Regions/file size" +msgstr "Regiões/tamanho de ficheiro" + +#: gtk_ardour/editor_region_list.cc:836 +msgid "Regions/file date" +msgstr "Regiões/data do ficheiro" + +#: gtk_ardour/editor_region_list.cc:840 +msgid "Regions/file system" +msgstr "Regiões/sistema de ficheiros" + +#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73 +#: gtk_ardour/editor_route_list.cc:231 +msgid "editor" +msgstr "" + +#: gtk_ardour/editor_route_list.cc:300 +msgid "Show All AbstractTracks" +msgstr "Mostar todas as faixas abstractas" + +#: gtk_ardour/editor_route_list.cc:301 +msgid "Hide All AbstractTracks" +msgstr "Esconder todas as faixas abstractas" + +#: gtk_ardour/editor_route_list.cc:302 +msgid "Show All AudioBus" +msgstr "Mostrar todos os barramentos audio" + +#: gtk_ardour/editor_route_list.cc:303 +msgid "Hide All AudioBus" +msgstr "Esconder todos os barramentos audio" + +#: gtk_ardour/editor_rulers.cc:311 +msgid "New location marker" +msgstr "Novo marcador de localização" + +#: gtk_ardour/editor_rulers.cc:312 +msgid "Clear all locations" +msgstr "Apagar todas as localizações" + +#: gtk_ardour/editor_rulers.cc:317 +msgid "Clear all ranges" +msgstr "Apagar todos os intervalos" + +#: gtk_ardour/editor_rulers.cc:326 +msgid "New Tempo" +msgstr "Novo Tempo" + +#: gtk_ardour/editor_rulers.cc:327 +msgid "Clear tempo" +msgstr "Apagar tempo" + +#: gtk_ardour/editor_rulers.cc:332 +msgid "New Meter" +msgstr "Novo VUímetro" + +#: gtk_ardour/editor_rulers.cc:333 +msgid "Clear meter" +msgstr "Apagar VUímetro" + +#: gtk_ardour/editor_rulers.cc:341 +msgid "Min:Secs" +msgstr "Min:Segs" + +#: gtk_ardour/editor_selection_list.cc:117 +msgid "name for chunk:" +msgstr "Nome para o trecho:" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Create chunk" +msgstr "Criar trecho" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Forget it" +msgstr "Esquecer" + +#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295 +msgid "add" +msgstr "acrescentar" + +#: gtk_ardour/editor_tempodisplay.cc:276 +#, fuzzy +msgid "add tempo mark" +msgstr "acrescentar marcador de região" + +#: gtk_ardour/editor_tempodisplay.cc:318 +#, fuzzy +msgid "add meter mark" +msgstr "acrescentar marcador métrico" + +#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383 +msgid "done" +msgstr "pronto" + +#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404 +msgid "replace tempo mark" +msgstr "substituir marcador de tempo" + +#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475 +msgid "programming error: marker for meter is not a meter marker!" +msgstr "" + +#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487 +msgid "remove tempo mark" +msgstr "remover marcador de tempo" + +#: gtk_ardour/editor_timefx.cc:50 +msgid "Quick but Ugly" +msgstr "Rápido mas Feio" + +#: gtk_ardour/editor_timefx.cc:51 +msgid "Skip Anti-aliasing" +msgstr "Ignorar Anti-aliasing" + +#: gtk_ardour/editor_timefx.cc:53 +msgid "Stretch/Shrink it" +msgstr "Alongar/Estreitar" + +#: gtk_ardour/editor_timefx.cc:57 +msgid "ardour: timestretch" +msgstr "ardour: alongamento temporal" + +#: gtk_ardour/editor_timefx.cc:58 +msgid "TimeStretchDialog" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83 +#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85 +msgid "TimeStretchButton" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:86 +msgid "TimeStretchProgress" +msgstr "" + +#: gtk_ardour/editor_timefx.cc:151 +msgid "timestretch cannot be started - thread creation error" +msgstr "" + +#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410 +#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189 +msgid "22.05kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413 +#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949 +#: gtk_ardour/export_dialog.cc:1191 +msgid "44.1kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416 +#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193 +msgid "48kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419 +#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195 +msgid "88.2kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422 +#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197 +msgid "96kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425 +#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199 +msgid "192kHz" +msgstr "" + +#: gtk_ardour/export_dialog.cc:73 +msgid "best" +msgstr "excelente" + +#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964 +msgid "fastest" +msgstr "rápido" + +#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966 +msgid "linear" +msgstr "linear" + +#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968 +msgid "better" +msgstr "bom" + +#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970 +msgid "intermediate" +msgstr "intermédio" + +#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979 +msgid "Rectangular" +msgstr "" + +#: gtk_ardour/export_dialog.cc:84 +msgid "Shaped Noise" +msgstr "Forma de Ruído" + +#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981 +msgid "Triangular" +msgstr "" + +#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336 +msgid "stereo" +msgstr "" + +#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497 +#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219 +#: gtk_ardour/utils.cc:334 +msgid "mono" +msgstr "" + +#: gtk_ardour/export_dialog.cc:97 +msgid "CUE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:98 +msgid "TOC" +msgstr "" + +#: gtk_ardour/export_dialog.cc:106 +msgid "FORMAT" +msgstr "FORMATO" + +#: gtk_ardour/export_dialog.cc:107 +msgid "SAMPLE RATE" +msgstr "FREQUÊNCIA DE AMOSTRAGEM" + +#: gtk_ardour/export_dialog.cc:108 +msgid "CONVERSION QUALITY" +msgstr "QUALIDADE DE CONVERSÃO" + +#: gtk_ardour/export_dialog.cc:109 +msgid "DITHER TYPE" +msgstr "TIPO DE EXTRAPOLAÇÃO" + +#: gtk_ardour/export_dialog.cc:110 +msgid "CD MARKER FILE TYPE" +msgstr "TIPO DE FICHEIRO MARCADORES CD" + +#: gtk_ardour/export_dialog.cc:111 +msgid "CHANNELS" +msgstr "CANAIS" + +#: gtk_ardour/export_dialog.cc:112 +msgid "FILE TYPE" +msgstr "TIPO DE FICHEIRO" + +#: gtk_ardour/export_dialog.cc:113 +msgid "SAMPLE FORMAT" +msgstr "FORMATO DE AMOSTRA" + +#: gtk_ardour/export_dialog.cc:114 +msgid "SAMPLE ENDIANNESS" +msgstr "REPRESENTAÇÃO BINÃRIA" + +#: gtk_ardour/export_dialog.cc:115 +#, fuzzy +msgid "EXPORT CD MARKER FILE ONLY" +msgstr "TIPO DE FICHEIRO MARCADORES CD" + +#: gtk_ardour/export_dialog.cc:116 +msgid "EXPORT TO FILE" +msgstr "EXPORTAR PARA FICHEIRO" + +#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118 +#: gtk_ardour/option_editor.cc:119 +msgid "Browse" +msgstr "Pesquisar" + +#: gtk_ardour/export_dialog.cc:119 +msgid "Specific tracks ..." +msgstr "Faixas específicas ..." + +#: gtk_ardour/export_dialog.cc:131 +msgid "ardour: export" +msgstr "ardour: exportar" + +#: gtk_ardour/export_dialog.cc:132 +msgid "ardour_export" +msgstr "" + +#: gtk_ardour/export_dialog.cc:156 +msgid "Output" +msgstr "Saída" + +#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626 +msgid "Track" +msgstr "Faixa" + +#: gtk_ardour/export_dialog.cc:287 +msgid "slereg" +msgstr "" + +#: gtk_ardour/export_dialog.cc:658 +msgid "Editor: cannot open \"%1\" as export file for CD toc file" +msgstr "" +"Editor: não foi possível abrir o ficheiro \"%1\" para exportação de " +"marcadores CD (TOC)" + +#: gtk_ardour/export_dialog.cc:780 +msgid "Editor: cannot open \"%1\" as export file for CD cue file" +msgstr "" +"Editor: não foi possível abrir o ficheiro \"%1\" para exportação de " +"marcadores CD (CUE)" + +#: gtk_ardour/export_dialog.cc:799 +msgid "WAV" +msgstr "" + +#: gtk_ardour/export_dialog.cc:1051 +msgid "Stop Export" +msgstr "Cancelar Exportação" + +#: gtk_ardour/gain_automation_time_axis.cc:60 +#, fuzzy +msgid "add gain automation event" +msgstr "acrescentar evento de automatização a " + +#: gtk_ardour/gain_meter.cc:68 +msgid "Cannot create slider pixmaps" +msgstr "" + +#: gtk_ardour/gain_meter.cc:83 +msgid "dbFS" +msgstr "" + +#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134 +#: gtk_ardour/gain_meter.cc:728 +msgid "pre" +msgstr "" + +#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724 +#, fuzzy +msgid "input" +msgstr "%1 entrada" + +#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732 +#, fuzzy +msgid "post" +msgstr "porta" + +#: gtk_ardour/gain_meter.cc:146 +msgid "tupni" +msgstr "" + +#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470 +#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537 +#, fuzzy +msgid "-inf" +msgstr "entrada" + +#: gtk_ardour/imageframe_socket_handler.cc:127 +msgid "Image Compositor Socket has been shutdown/closed" +msgstr "O ligação ao Compositor de Imagem foi desligada/fechada" + +#: gtk_ardour/imageframe_time_axis.cc:295 +#, fuzzy +msgid "0.5 seconds" +msgstr "Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259 +#, fuzzy +msgid "1 seconds" +msgstr "Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260 +#, fuzzy +msgid "1.5 seconds" +msgstr "Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261 +#, fuzzy +msgid "2 seconds" +msgstr "Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262 +#, fuzzy +msgid "2.5 seconds" +msgstr "Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263 +#, fuzzy +msgid "3 seconds" +msgstr "Segundos" + +#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268 +#, fuzzy +msgid "Duration (sec)" +msgstr "Arrastar regiões" + +#: gtk_ardour/imageframe_time_axis.cc:310 +#, fuzzy +msgid "Remove Frame" +msgstr "Remover Campo" + +#: gtk_ardour/imageframe_time_axis.cc:313 +#, fuzzy +msgid "Image Frame" +msgstr "Quadros CD" + +#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274 +#, fuzzy +msgid "Rename Track" +msgstr "Renomear" + +#: gtk_ardour/io_selector.cc:64 +msgid "%1 input" +msgstr "%1 entrada" + +#: gtk_ardour/io_selector.cc:66 +msgid "%1 output" +msgstr "%1 saída" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103 +msgid "Inputs" +msgstr "Entradas" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104 +msgid "Outputs" +msgstr "Saídas" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Input" +msgstr "acrescentar entrada" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Output" +msgstr "acrescentar saída" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Input" +msgstr "Remover ponto de sincronia" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Output" +msgstr "No.Saídas" + +#: gtk_ardour/io_selector.cc:144 +#, fuzzy +msgid "Disconnect All" +msgstr "Desligar" + +#: gtk_ardour/io_selector.cc:158 +msgid "Available connections" +msgstr "Ligações disponíveis" + +#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636 +#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724 +msgid "port" +msgstr "porta" + +#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587 +msgid "There are no more JACK ports available." +msgstr "" + +#: gtk_ardour/io_selector.cc:790 +msgid "ardour: " +msgstr "" + +#: gtk_ardour/keyboard.cc:419 +msgid "KeyboardTarget: keyname \"%1\" is unknown." +msgstr "" + +#: gtk_ardour/keyboard.cc:645 +msgid "" +"Your system is completely broken - NumLock uses \"%1\"as its modifier. This " +"is madness - see the man page for xmodmap to find out how to fix this." +msgstr "" + +#: gtk_ardour/keyboard.cc:653 +msgid "" +"Your system generates \"%1\" when the NumLock key is pressed. This can cause " +"problems when editing so Ardour will use %2 to mean Meta rather than %1" +msgstr "" + +#: gtk_ardour/keyboard.cc:714 +msgid "You have %1 keys bound to \"mod1\"" +msgstr "Existem %1 teclas associadas a \"mod1\"" + +#: gtk_ardour/keyboard.cc:729 +msgid "You have %1 keys bound to \"mod2\"" +msgstr "Existem %1 teclas associadas a \"mod2\"" + +#: gtk_ardour/keyboard.cc:744 +msgid "You have %1 keys bound to \"mod3\"" +msgstr "Existem %1 teclas associadas a \"mod3\"" + +#: gtk_ardour/keyboard.cc:759 +msgid "You have %1 keys bound to \"mod4\"" +msgstr "Existem %1 teclas associadas a \"mod4\"" + +#: gtk_ardour/keyboard.cc:774 +msgid "You have %1 keys bound to \"mod5\"" +msgstr "Existem %1 teclas associadas a \"mod5\"" + +#: gtk_ardour/keyboard_target.cc:72 +msgid "KeyboardTarget: empty string passed to add_binding." +msgstr "KeyboardTarget: combinação nula ou inválida." + +#: gtk_ardour/keyboard_target.cc:78 +msgid "KeyboardTarget: no translation found for \"%1\"" +msgstr "KeyboardTarget: não existe tradução para \"%1\"" + +#: gtk_ardour/keyboard_target.cc:83 +msgid "KeyboardTarget: unknown action \"%1\"" +msgstr "KeyboardTarget: acção desconhecida \"%1\"" + +#: gtk_ardour/keyboard_target.cc:248 +msgid "misformed binding node - ignored" +msgstr "combinação mal formada - ignorada" + +#: gtk_ardour/library_ui.cc:62 +msgid "Soundfile Library" +msgstr "Audioteca" + +#: gtk_ardour/library_ui.cc:63 +msgid "Filesystem" +msgstr "Ficheiros" + +#: gtk_ardour/library_ui.cc:66 +msgid "Split Channels" +msgstr "Separar Canais" + +#: gtk_ardour/library_ui.cc:69 +msgid "ardour: soundfile selector" +msgstr "ardor: selecção de ficheiro audio" + +#: gtk_ardour/library_ui.cc:430 +msgid "Add to Library..." +msgstr "Acrescentar à Audioteca..." + +#: gtk_ardour/library_ui.cc:431 +msgid "Remove..." +msgstr "Remover..." + +#: gtk_ardour/library_ui.cc:432 +msgid "Find..." +msgstr "Procurar..." + +#: gtk_ardour/library_ui.cc:433 +msgid "Add Folder" +msgstr "Acrescentar Directório/Pasta" + +#: gtk_ardour/library_ui.cc:434 +msgid "Add audio file or directory" +msgstr "Acrescentar ficheiro ou directório/pasta" + +#: gtk_ardour/library_ui.cc:713 +msgid "Importing" +msgstr "Em importação" + +#: gtk_ardour/library_ui.cc:748 +msgid "%1 not added to database" +msgstr "%1 não foram acrescentados" + +#: gtk_ardour/library_ui.cc:767 +msgid "Folder name:" +msgstr "Nome do directório/pasta:" + +#: gtk_ardour/library_ui.cc:838 +msgid "Should not be reached" +msgstr "Não deve ser alcançada" + +#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096 +msgid "file \"%1\" could not be opened" +msgstr "não foi possível abrir o ficheiro \"%1\"" + +#: gtk_ardour/library_ui.cc:956 +msgid "Field" +msgstr "Campo" + +#: gtk_ardour/library_ui.cc:957 +msgid "Value" +msgstr "Valor" + +#: gtk_ardour/library_ui.cc:973 +msgid "Stop" +msgstr "Parar" + +#: gtk_ardour/library_ui.cc:974 +msgid "Add Field..." +msgstr "Acrescentar Campo..." + +#: gtk_ardour/library_ui.cc:975 +msgid "Remove Field" +msgstr "Remover Campo" + +#: gtk_ardour/library_ui.cc:979 +msgid "Soundfile Info" +msgstr "Informações" + +#: gtk_ardour/library_ui.cc:1106 +msgid "file \"%1\" appears not to be an audio file" +msgstr "" + +#: gtk_ardour/library_ui.cc:1159 +msgid "Could not read file: %1 (%2)." +msgstr "Não foi possível ler o ficheiro \"%1\" (%2)" + +#: gtk_ardour/library_ui.cc:1177 +msgid "Could not access soundfile: " +msgstr "Não foi possível aceder ao ficheiros audio: " + +#: gtk_ardour/library_ui.cc:1222 +msgid "Field name:" +msgstr "Nome para o campo:" + +#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367 +msgid "Field value:" +msgstr "Valor para o campo:" + +#: gtk_ardour/library_ui.cc:1295 +msgid "Find" +msgstr "Procurar" + +#: gtk_ardour/library_ui.cc:1296 +msgid "AND" +msgstr "E" + +#: gtk_ardour/library_ui.cc:1297 +msgid "OR" +msgstr "OU" + +#: gtk_ardour/library_ui.cc:1300 +msgid "ardour: locate soundfiles" +msgstr "ardour: localizar ficheiros audio" + +#: gtk_ardour/library_ui.cc:1426 +msgid "Results" +msgstr "Resultados" + +#: gtk_ardour/library_ui.cc:1427 +msgid "Uris" +msgstr "URIs" + +#: gtk_ardour/library_ui.cc:1439 +msgid "Create multi-channel region" +msgstr "Criar região multi-canal" + +#: gtk_ardour/library_ui.cc:1442 +msgid "Ardour: Search Results" +msgstr "Ardour: Resultados da Procura" + +#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50 +msgid "Set" +msgstr "Seleccionar" + +#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51 +msgid "Go" +msgstr "Ir" + +#: gtk_ardour/location_ui.cc:54 +msgid "CD" +msgstr "" + +#: gtk_ardour/location_ui.cc:55 +msgid "Hidden" +msgstr "Esconder" + +#: gtk_ardour/location_ui.cc:57 +msgid "SCMS" +msgstr "" + +#: gtk_ardour/location_ui.cc:58 +msgid "Pre-Emphasis" +msgstr "" + +#: gtk_ardour/location_ui.cc:592 +msgid "Add New Location" +msgstr "Adicionar Nova Localização" + +#: gtk_ardour/location_ui.cc:593 +msgid "Add New Range" +msgstr "Adicionar Novo Intervalo" + +#: gtk_ardour/location_ui.cc:597 +msgid "ardour: locations" +msgstr "ardour: localizações" + +#: gtk_ardour/location_ui.cc:598 +msgid "ardour_locations" +msgstr "" + +#: gtk_ardour/location_ui.cc:629 +#, fuzzy +msgid "Location (CD Index) Markers" +msgstr "Localizações" + +#: gtk_ardour/location_ui.cc:649 +#, fuzzy +msgid "Range (CD Track) Markers" +msgstr "Intervalos" + +#: gtk_ardour/location_ui.cc:814 +msgid "add range marker" +msgstr "acrescentar marcador de região" + +#: gtk_ardour/main.cc:76 +msgid "ardour is killing itself for a clean exit\n" +msgstr "ardour em modo de auto-destruição para uma saída em beleza\n" + +#: gtk_ardour/main.cc:85 +msgid "stopping user interface\n" +msgstr "interface homem-máquina em fase terminal\n" + +#: gtk_ardour/main.cc:104 +#, fuzzy, c-format +msgid "%d(%d): received signal %d\n" +msgstr "%d: sinal %d recebido\n" + +#: gtk_ardour/main.cc:190 +msgid "cannot become new process group leader (%1)" +msgstr "" + +#: gtk_ardour/main.cc:217 +msgid "cannot setup signal handling for %1" +msgstr "não foi possível estabelecer receptor de sinal %1" + +#: gtk_ardour/main.cc:228 +msgid "cannot set default signal mask (%1)" +msgstr "não foi possível estabelecer máscara de sinal %1" + +#: gtk_ardour/main.cc:253 +msgid "" +"Without a UI style file, ardour will look strange.\n" +" Please set ARDOUR_UI_RC to point to a valid UI style file" +msgstr "" +"O Ardour vai aparecer algo esquisito sem um ficheiro\n" +"de estilo visual para o interface de utilizador (UI).\n" +"Por favor, indique um ficheiro de estilo visual válido em ARDOUR_UI_RC " +"(variável de ambiente)" + +#: gtk_ardour/main.cc:292 +msgid "" +"Ardour could not connect to JACK.\n" +"There are several possible reasons:\n" +"\n" +"1) JACK is not running.\n" +"2) JACK is running as another user, perhaps root.\n" +"3) There is already another client called \"ardour\".\n" +"\n" +"Please consider the possibilities, and perhaps (re)start JACK." +msgstr "" +"Não foi possível estabelecer ligação com o serviço JACK.\n" +"Podem existir várias razões para tal:\n" +"\n" +"1) O serviço JACK não se encontra activo.\n" +"2) O serviço JACK encontra-se activo por outro utilizador, talvez root.\n" +"3) Já se encontra activo outro client chamado \"ardour\".\n" +"\n" +"Por favor, considere estas possibilidades e (re)inicie o serviço JACK." + +#: gtk_ardour/main.cc:305 +msgid "ardour: unplugged" +msgstr "ardour: desligado" + +#: gtk_ardour/main.cc:363 +msgid "Ardour/GTK " +msgstr "" + +#: gtk_ardour/main.cc:365 +msgid "" +"\n" +" (built using " +msgstr "" + +#: gtk_ardour/main.cc:369 +#, fuzzy +msgid " with libardour " +msgstr " em execução com libardour " + +#: gtk_ardour/main.cc:374 +msgid " and GCC version " +msgstr "" + +#: gtk_ardour/main.cc:384 +msgid "Copyright (C) 1999-2005 Paul Davis" +msgstr "" + +#: gtk_ardour/main.cc:385 +msgid "" +"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel " +"Baker" +msgstr "" + +#: gtk_ardour/main.cc:387 +msgid "Ardour comes with ABSOLUTELY NO WARRANTY" +msgstr "Ardour é fornecido ABSOLUTAMENTE SEM QUALQUER GARANTIA" + +#: gtk_ardour/main.cc:388 +msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +msgstr "" + +#: gtk_ardour/main.cc:389 +msgid "This is free software, and you are welcome to redistribute it " +msgstr "Sendo software livre, é permitida e até encorajada a sua distribuição" + +#: gtk_ardour/main.cc:390 +#, fuzzy +msgid "under certain conditions; see the source for copying conditions." +msgstr "" +"desde que sejam respeitadas algumas condições; para mais informações, leia " +"por favor o ficheiro COPYING." + +#: gtk_ardour/main.cc:399 +msgid "could not create ARDOUR GUI" +msgstr "não foi possível criar o interface gráfico (GUI)" + +#: gtk_ardour/main.cc:419 +msgid "Could not connect to JACK server as \"%1\"" +msgstr "Não foi possível conectar ao serviço JACK como \"%1\"" + +#: gtk_ardour/main.cc:424 +msgid "could not initialize Ardour." +msgstr "não foi possível inicializar o Ardour" + +#: gtk_ardour/main.cc:435 +msgid "could not load command line session \"%1\"" +msgstr "não foi possível carregar a sessão de linha de comando \"%1\"" + +#: gtk_ardour/main.cc:455 +msgid "" +"\n" +"\n" +"A session named \"%1\" already exists.\n" +"To avoid this message, start ardour as \"ardour %1" +msgstr "" + +#: gtk_ardour/main.cc:466 +msgid "" +"\n" +"\n" +"No session named \"%1\" exists.\n" +"To create it from the command line, start ardour as \"ardour --new %1" +msgstr "" + +#: gtk_ardour/marker.cc:354 +#, fuzzy +msgid "MarkerText" +msgstr "Marcas" + +#: gtk_ardour/marker_time_axis.cc:271 +#, fuzzy +msgid "Remove Marker" +msgstr "remover marcador" + +#: gtk_ardour/marker_time_axis.cc:273 +#, fuzzy +msgid "Marker" +msgstr "Marcas" + +#: gtk_ardour/meter_bridge.cc:74 +msgid "ardour: meter bridge" +msgstr "ardour: VUímetro" + +#: gtk_ardour/meter_bridge.cc:75 +msgid "ardour_meter_bridge" +msgstr "" + +#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93 +#, c-format +msgid "# of %u-sample overs" +msgstr "# de %u-quadros" + +#: gtk_ardour/meter_bridge_strip.cc:219 +msgid "New name for meter:" +msgstr "Novo nome para o VUímetro:" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507 +#: gtk_ardour/region_editor.cc:45 +msgid "mute" +msgstr "mudo" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508 +msgid "solo" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506 +msgid "RECORD" +msgstr "GRAVAR" + +#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514 +msgid "polarity" +msgstr "polaridade" + +#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509 +msgid "comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810 +msgid "INPUT" +msgstr "ENTRADA" + +#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831 +msgid "OUTPUT" +msgstr "SAÃDA" + +#: gtk_ardour/mixer_strip.cc:173 +msgid "Pan automation mode" +msgstr "Modo de automatização de panorâmica" + +#: gtk_ardour/mixer_strip.cc:174 +msgid "Gain automation mode" +msgstr "Modo de automatização de ganho" + +#: gtk_ardour/mixer_strip.cc:176 +msgid "Pan automation type" +msgstr "Tipo de automatização de panorâmica" + +#: gtk_ardour/mixer_strip.cc:177 +msgid "Gain automation type" +msgstr "Tipo de automatização de ganho" + +#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232 +#: gtk_ardour/mixer_strip.cc:979 +msgid "trim" +msgstr "recorte" + +#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233 +#: gtk_ardour/mixer_strip.cc:983 +msgid "abs" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:240 +msgid "gain automation mode" +msgstr "modo de automatização de ganho" + +#: gtk_ardour/mixer_strip.cc:241 +msgid "pan automation mode" +msgstr "modo de automatização de panorâmica" + +#: gtk_ardour/mixer_strip.cc:242 +msgid "gain automation state" +msgstr "ponto de automatização de ganho" + +#: gtk_ardour/mixer_strip.cc:243 +msgid "pan automation state" +msgstr "ponto de automatização de panorâmica" + +#: gtk_ardour/mixer_strip.cc:259 +msgid "varispeed" +msgstr "velocidade variável" + +#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174 +msgid "click to add/edit comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:463 +msgid "unknown strip width \"%1\" in XML GUI information" +msgstr "" +"largura desconhecida \"%1\" na informação XML para o interface gráfico (GUI)" + +#: gtk_ardour/mixer_strip.cc:522 +msgid "REC" +msgstr "GRAV" + +#: gtk_ardour/mixer_strip.cc:525 +#, fuzzy +msgid "cmt" +msgstr "corte" + +#: gtk_ardour/mixer_strip.cc:530 +msgid "pol" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620 +#: gtk_ardour/redirect_box.cc:1180 +msgid "Not connected to JACK - no I/O changes are possible" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667 +msgid "could not register new ports required for that connection" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:813 +msgid "IN" +msgstr "ENTRADA" + +#: gtk_ardour/mixer_strip.cc:834 +msgid "OUT" +msgstr "SAÃDA" + +#: gtk_ardour/mixer_strip.cc:950 +msgid "aplay" +msgstr "aRepr" + +#: gtk_ardour/mixer_strip.cc:956 +msgid "awrite" +msgstr "aGrav" + +#: gtk_ardour/mixer_strip.cc:1134 +#, fuzzy +msgid ": comment editor" +msgstr "Não foi possível iniciar o painel principal de edição (editor)" + +#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224 +msgid "no group" +msgstr "sem grupo" + +#: gtk_ardour/mixer_strip.cc:1227 +msgid "~G" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:52 +msgid "Strips" +msgstr "Painéis" + +#: gtk_ardour/mixer_ui.cc:56 +msgid "Snapshots" +msgstr "Capturas" + +#: gtk_ardour/mixer_ui.cc:61 +msgid "***" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17 +#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144 +#: gtk_ardour/tempo_dialog.cc:162 +msgid "Bar" +msgstr "Compasso" + +#: gtk_ardour/mixer_ui.cc:121 +msgid "Mix Groups" +msgstr "Grupos" + +#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373 +msgid "ardour: mixer" +msgstr "ardour: misturador" + +#: gtk_ardour/mixer_ui.cc:192 +msgid "ardour_mixer" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:342 +msgid "ardour: mixer: " +msgstr "ardour: misturador: " + +#: gtk_ardour/mixer_ui.cc:641 +msgid "signal" +msgstr "sinal" + +#: gtk_ardour/mixer_ui.cc:672 +msgid "Show All AudioTrack MixerStrips" +msgstr "Mostrar painéis de mistura de todas as faixas audio" + +#: gtk_ardour/mixer_ui.cc:673 +msgid "Hide All AudioTrack MixerStrips" +msgstr "Esconder painéis de mistura de todas as faixas audio" + +#: gtk_ardour/mixer_ui.cc:674 +msgid "Show All AudioBus MixerStrips" +msgstr "Mostrar painéis de mistura de todos os barramentos audio" + +#: gtk_ardour/mixer_ui.cc:675 +msgid "Hide All AudioBus MixerStrips" +msgstr "Esconder painéis de mistura de todos os barramentos audio" + +#: gtk_ardour/mixer_ui.cc:687 +msgid "track display list item for renamed strip not found!" +msgstr "não foi encontrada qualquer faixa para o painel de mistura" + +#: gtk_ardour/mixer_ui.cc:700 +msgid "Name for new mix group" +msgstr "Nome para o novo grupo de mistura" + +#: gtk_ardour/new_session_dialog.cc:39 +msgid "Session name:" +msgstr "Nome de sessão:" + +#: gtk_ardour/new_session_dialog.cc:39 +msgid "Create" +msgstr "Criar" + +#: gtk_ardour/new_session_dialog.cc:40 +msgid "use control outs" +msgstr "usar saídas de controlo" + +#: gtk_ardour/new_session_dialog.cc:41 +msgid "use master outs" +msgstr "usar saídas principais" + +#: gtk_ardour/new_session_dialog.cc:42 +msgid "automatically connect track inputs to physical ports" +msgstr "ligar entradas físicas automaticamente" + +#: gtk_ardour/new_session_dialog.cc:43 +msgid "automatically connect track outputs to master outs" +msgstr "ligar saídas principais automaticamente" + +#: gtk_ardour/new_session_dialog.cc:44 +msgid "automatically connect track outputs to physical ports" +msgstr "ligar saídas físicas automaticamente" + +#: gtk_ardour/new_session_dialog.cc:45 +msgid "manually connect track outputs" +msgstr "ligar saídas manualmente" + +#: gtk_ardour/new_session_dialog.cc:50 +msgid "Advanced..." +msgstr "Avançado..." + +#: gtk_ardour/new_session_dialog.cc:52 +msgid "show again" +msgstr "mostrar este diálogo novamente" + +#: gtk_ardour/new_session_dialog.cc:55 +msgid "Hardware Inputs: use" +msgstr "Entradas Físicas: usar" + +#: gtk_ardour/new_session_dialog.cc:56 +msgid "Hardware Outputs: use" +msgstr "Saídas Físicas: usar" + +#: gtk_ardour/new_session_dialog.cc:62 +msgid "new session setup" +msgstr "nova sessão" + +#: gtk_ardour/new_session_dialog.cc:63 +msgid "ardour_new_session" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:72 +msgid "This session will playback and record at %1 Hz" +msgstr "Esta sessão irá reproduzir e gravar a %1 Hz" + +#: gtk_ardour/new_session_dialog.cc:74 +msgid "" +"This rate is set by JACK and cannot be changed.\n" +"If you want to use a different sample rate\n" +"please exit and restart JACK" +msgstr "" +"Esta frequência de amostragem é pré-estabelecida\n" +"pelo serviço JACK e não pode ser alterada.\n" +"Se pretende usar uma frequência de amostragem diferente\n" +"terá de sair e reiniciar o serviço JACK" + +#: gtk_ardour/new_session_dialog.cc:155 +#, fuzzy +msgid "Session template" +msgstr "Modelo de sessão" + +#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20 +#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146 +#: gtk_ardour/tempo_dialog.cc:164 +msgid "Location" +msgstr "Localização" + +#: gtk_ardour/new_session_dialog.cc:178 +msgid "Configuration" +msgstr "Configuração" + +#: gtk_ardour/new_session_dialog.cc:269 +msgid "blank" +msgstr "vazio" + +#: gtk_ardour/new_session_dialog.cc:328 +msgid "No template - create tracks/busses manually" +msgstr "Sem modelo - criar faixas/barramentos manualmente" + +#: gtk_ardour/new_session_dialog.cc:337 +msgid "No template" +msgstr "Sem modelo" + +#: gtk_ardour/option_editor.cc:48 +msgid "Internal" +msgstr "Interno" + +#: gtk_ardour/option_editor.cc:49 +msgid "Slave to MTC" +msgstr "Escravo MTC" + +#: gtk_ardour/option_editor.cc:50 +msgid "Sync with JACK" +msgstr "Sincronia JACK" + +#: gtk_ardour/option_editor.cc:51 +msgid "never used but stops crashes" +msgstr "nunca usado mas evita problemas" + +#: gtk_ardour/option_editor.cc:56 +#, fuzzy +msgid "Later regions are higher" +msgstr "Descer a região em um nível" + +#: gtk_ardour/option_editor.cc:57 +msgid "Most recently added/moved/trimmed regions are higher" +msgstr "" + +#: gtk_ardour/option_editor.cc:58 +#, fuzzy +msgid "Most recently added regions are higher" +msgstr "Descer a região em um nível" + +#: gtk_ardour/option_editor.cc:63 +#, fuzzy +msgid "Span entire region overlap" +msgstr "Elevar a região em um nível" + +#: gtk_ardour/option_editor.cc:64 +msgid "Short fades at the start of the overlap" +msgstr "" + +#: gtk_ardour/option_editor.cc:82 +#, fuzzy +msgid "Automatically create crossfades" +msgstr "Desvanecimento cruzado automático em sobreposição" + +#: gtk_ardour/option_editor.cc:83 +msgid "New full-overlap crossfades are unmuted" +msgstr "" + +#: gtk_ardour/option_editor.cc:84 +#, fuzzy +msgid "Region layering mode" +msgstr "Finais de região" + +#: gtk_ardour/option_editor.cc:85 +#, fuzzy +msgid "Crossfade model" +msgstr "Desvanecimento cruzado" + +#: gtk_ardour/option_editor.cc:90 +msgid "Latched solo" +msgstr "Solo retido" + +#: gtk_ardour/option_editor.cc:91 +msgid "Solo via bus" +msgstr "Solo por barramento" + +#: gtk_ardour/option_editor.cc:96 +msgid "Show waveforms while recording" +msgstr "Mostrar formas de onda enquanto grava" + +#: gtk_ardour/option_editor.cc:97 +msgid "Narrow mixer strips" +msgstr "Estreitar painéis de mistura" + +#: gtk_ardour/option_editor.cc:98 +msgid "Show measure lines" +msgstr "Mostrar linhas de tempo" + +#: gtk_ardour/option_editor.cc:99 +msgid "Follow playhead" +msgstr "Seguir o cursor de reprodução" + +#: gtk_ardour/option_editor.cc:103 +msgid "Send MTC" +msgstr "Enviar MTC" + +#: gtk_ardour/option_editor.cc:104 +msgid "Send MMC" +msgstr "Enviar MMC" + +#: gtk_ardour/option_editor.cc:105 +msgid "JACK time master" +msgstr "Supervisor de tempo JACK" + +#: gtk_ardour/option_editor.cc:107 +#, fuzzy +msgid "SMPTE offset is negative" +msgstr "Deslocamento SMPTE" + +#: gtk_ardour/option_editor.cc:111 +#, fuzzy +msgid "Send MIDI parameter feedback" +msgstr "Enviar resposta a parametros MIDI" + +#: gtk_ardour/option_editor.cc:112 +#, fuzzy +msgid "MIDI parameter control" +msgstr "Receber controlo de parametros MIDI" + +#: gtk_ardour/option_editor.cc:113 +#, fuzzy +msgid "MMC control" +msgstr "Porta MMC" + +#: gtk_ardour/option_editor.cc:131 +#, fuzzy +msgid "Auto-connect new track inputs to hardware" +msgstr "Ligar novas faixas automaticamente" + +#: gtk_ardour/option_editor.cc:132 +#, fuzzy +msgid "Auto-connect new track outputs to hardware" +msgstr "Ligar novas faixas automaticamente" + +#: gtk_ardour/option_editor.cc:133 +#, fuzzy +msgid "Auto-connect new track outputs to master bus" +msgstr "ligar saídas principais automaticamente" + +#: gtk_ardour/option_editor.cc:134 +#, fuzzy +msgid "Manually connect new track outputs" +msgstr "ligar saídas manualmente" + +#: gtk_ardour/option_editor.cc:135 +msgid "Use Hardware Monitoring" +msgstr "Usar monitorização física" + +#: gtk_ardour/option_editor.cc:136 +msgid "Use Software Monitoring" +msgstr "Usar monitorização lógica" + +#: gtk_ardour/option_editor.cc:137 +msgid "Stop plugins with transport" +msgstr "Suspender efeitos/plug-ins com transporte" + +#: gtk_ardour/option_editor.cc:138 +msgid "Run plugins while recording" +msgstr "Executar efeitos/plug-ins durante a gravação" + +#: gtk_ardour/option_editor.cc:139 +#, fuzzy +msgid "Verify remove last capture" +msgstr "Remover a última captura" + +#: gtk_ardour/option_editor.cc:140 +msgid "Stop recording on xrun" +msgstr "Suspender a gravação em caso de falha sincrónica (XRUN)" + +#: gtk_ardour/option_editor.cc:141 +msgid "Stop transport at end of session" +msgstr "Suspender o transporte no final da sessão" + +#: gtk_ardour/option_editor.cc:142 +msgid "Debug keyboard events" +msgstr "Depurar eventos programáticos de teclado" + +#: gtk_ardour/option_editor.cc:143 +msgid "-12dB gain reduction for ffwd/rew" +msgstr "" + +#: gtk_ardour/option_editor.cc:152 +msgid "ardour: options editor" +msgstr "ardour: opções" + +#: gtk_ardour/option_editor.cc:153 +msgid "ardour_option_editor" +msgstr "" + +#: gtk_ardour/option_editor.cc:183 +msgid "Misc" +msgstr "Miscelânea" + +#: gtk_ardour/option_editor.cc:184 +msgid "Sync" +msgstr "Sincronia" + +#: gtk_ardour/option_editor.cc:185 +msgid "Paths/Files" +msgstr "Directórios/Ficheiros" + +#: gtk_ardour/option_editor.cc:186 +msgid "Display" +msgstr "Visualização" + +#: gtk_ardour/option_editor.cc:187 +msgid "Kbd/Mouse" +msgstr "Teclado/Rato" + +#: gtk_ardour/option_editor.cc:188 +msgid "Click" +msgstr "Metrónomo" + +#: gtk_ardour/option_editor.cc:190 +msgid "Layers & Fades" +msgstr "" + +#: gtk_ardour/option_editor.cc:195 +msgid "MIDI" +msgstr "" + +#: gtk_ardour/option_editor.cc:268 +msgid "24 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:270 +msgid "25 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:272 +msgid "30 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:278 +msgid "30 FPS drop" +msgstr "" + +#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379 +#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736 +#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800 +msgid "Medium" +msgstr "" + +#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738 +#: gtk_ardour/option_editor.cc:804 +#, fuzzy +msgid "Faster" +msgstr "Rápido" + +#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714 +#: gtk_ardour/option_editor.cc:776 +#, fuzzy +msgid "Short" +msgstr "porta" + +#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716 +#: gtk_ardour/option_editor.cc:780 +msgid "Long" +msgstr "" + +#: gtk_ardour/option_editor.cc:396 +msgid "Broadcast WAVE/floating point" +msgstr "WAVE/vírgula flutuante (Broadcast)" + +#: gtk_ardour/option_editor.cc:397 +msgid "WAVE/floating point" +msgstr "WAVE/vírgula flutuante" + +#: gtk_ardour/option_editor.cc:417 +msgid "session RAID path" +msgstr "directório RAID de sessão" + +#: gtk_ardour/option_editor.cc:422 +msgid "Native Format" +msgstr "Formato Nativo" + +#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460 +#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409 +msgid "internal" +msgstr "interno" + +#: gtk_ardour/option_editor.cc:537 +msgid "Short crossfade length (msecs)" +msgstr "" + +#: gtk_ardour/option_editor.cc:710 +msgid "Meter Peak Hold" +msgstr "" + +#: gtk_ardour/option_editor.cc:730 +msgid "Meter Falloff" +msgstr "" + +#: gtk_ardour/option_editor.cc:847 +msgid "Positional Sync" +msgstr "Sicronia de Posição" + +#: gtk_ardour/option_editor.cc:902 +msgid "SMPTE Frames/second" +msgstr "Quadros SMPTE/segundo" + +#: gtk_ardour/option_editor.cc:903 +msgid "SMPTE Offset" +msgstr "Deslocamento SMPTE" + +#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013 +#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211 +#, fuzzy +msgid "online" +msgstr "linear" + +#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014 +#: gtk_ardour/option_editor.cc:1208 +#, fuzzy +msgid "offline" +msgstr "linear" + +#: gtk_ardour/option_editor.cc:1319 +msgid "Use as click" +msgstr "Usar como metrónomo" + +#: gtk_ardour/option_editor.cc:1344 +msgid "Use as click emphasis" +msgstr "Usar como metrónomo acentuado" + +#: gtk_ardour/option_editor.cc:1478 +msgid "--unknown--" +msgstr "--desconhecido--" + +#: gtk_ardour/option_editor.cc:1595 +msgid "Click audio file" +msgstr "Ficheiro audio para metrónomo" + +#: gtk_ardour/option_editor.cc:1601 +msgid "Click emphasis audiofile" +msgstr "Ficheiro audio para metrónomo acentuado" + +#: gtk_ardour/option_editor.cc:1638 +msgid "" +"The auditioner is a dedicated mixer strip used\n" +"for listening to specific regions outside the context\n" +"of the overall mix. It can be connected just like any\n" +"other mixer strip." +msgstr "" +"O auditor é um painel de mistura dedicado\n" +"para a escuta de determinadas regiões fora do contexto\n" +"da mistura geral. Pode ser inter-conectado tal como\n" +"qualquer outro painel de mistura." + +#: gtk_ardour/option_editor.cc:1887 +msgid "Edit using" +msgstr "Editar com" + +#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924 +msgid "+ button" +msgstr "+ botão" + +#: gtk_ardour/option_editor.cc:1917 +msgid "Delete using" +msgstr "Eliminar com" + +#: gtk_ardour/option_editor.cc:1947 +msgid "Ignore snap using" +msgstr "Ignorar ajuste com" + +#: gtk_ardour/opts.cc:46 +msgid "Usage: " +msgstr "Uso: " + +#: gtk_ardour/opts.cc:47 +msgid " -v, --version Show version information\n" +msgstr " -v, --version Mostrar informação sobre versão\n" + +#: gtk_ardour/opts.cc:48 +msgid " -h, --help Print this message\n" +msgstr " -h, --help Mostrar esta mesma mensagem\n" + +#: gtk_ardour/opts.cc:49 +msgid "" +" -b, --bindings Print all possible keyboard binding " +"names\n" +msgstr "" +" -b, --bindings Mostrar todas as associações de teclado " +"possíveis\n" + +#: gtk_ardour/opts.cc:50 +#, fuzzy +msgid " -n, --show-splash Show splash screen\n" +msgstr "" +" -n, --no-splash Não mostrar ecran de apresentação " +"inicial\n" + +#: gtk_ardour/opts.cc:51 +#, fuzzy +msgid "" +" -c, --name name Use a specific jack client name, default " +"is ardour\n" +msgstr "" +" -c, --jack-client-name name Empregar um nome de cliente JACK " +"específico (ardour)\n" + +#: gtk_ardour/opts.cc:52 +#, fuzzy +msgid "" +" -N, --new session-name Create a new session from the command " +"line\n" +msgstr " [session-name] Nome de sessão a carregar\n" + +#: gtk_ardour/opts.cc:53 +msgid "" +" -o, --use-hw-optimizations Try to use h/w specific optimizations\n" +msgstr "" + +#: gtk_ardour/opts.cc:55 +#, fuzzy +msgid " -V, --novst Do not use VST support\n" +msgstr " -V, --novst Não usar suporte VST inicial\n" + +#: gtk_ardour/opts.cc:57 +msgid " [session-name] Name of session to load\n" +msgstr " [session-name] Nome de sessão a carregar\n" + +#: gtk_ardour/opts.cc:58 +msgid " -C, --curvetest filename Curve algorithm debugger\n" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:58 +msgid "You can't graphically edit panning of more than stream" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:78 +#, fuzzy +msgid "add pan automation event" +msgstr "acrescentar evento de automatização a " + +#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441 +msgid "Bypass" +msgstr "Ignorar" + +#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222 +#, fuzzy +msgid "link" +msgstr "entrada" + +#: gtk_ardour/panner_ui.cc:103 +msgid "panning link control" +msgstr "" + +#: gtk_ardour/panner_ui.cc:105 +msgid "panning link direction" +msgstr "" + +#: gtk_ardour/panner_ui.cc:232 +msgid "L" +msgstr "" + +#: gtk_ardour/panner_ui.cc:344 +#, c-format +msgid "panner for channel %u" +msgstr "" + +#: gtk_ardour/panner_ui.cc:451 +#, fuzzy +msgid "Reset all" +msgstr "reiniciar" + +#: gtk_ardour/playlist_selector.cc:46 +msgid "Playlists grouped by track" +msgstr "" + +#: gtk_ardour/playlist_selector.cc:53 +#, fuzzy +msgid "close" +msgstr "Fechar" + +#: gtk_ardour/playlist_selector.cc:59 +#, fuzzy +msgid "ardour: playlists" +msgstr "ardour: efeitos/plug-ins" + +#: gtk_ardour/playlist_selector.cc:104 +#, fuzzy +msgid "ardour: playlist for " +msgstr "ardour: efeitos/plug-ins" + +#: gtk_ardour/playlist_selector.cc:122 +#, fuzzy +msgid "Other tracks" +msgstr "retocar faixa" + +#: gtk_ardour/playlist_selector.cc:138 +msgid "unassigned" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:41 +msgid "Available LADSPA plugins" +msgstr "Efeitos/plug-ins LADSPA disponíveis" + +#: gtk_ardour/plugin_selector.cc:42 +msgid "Type" +msgstr "Tipo" + +#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51 +msgid "# Inputs" +msgstr "No.Entradas" + +#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52 +msgid "# Outputs" +msgstr "No.Saídas" + +#: gtk_ardour/plugin_selector.cc:50 +msgid "Available VST plugins" +msgstr "Efeitos/plug-ins VST disponíveis" + +#: gtk_ardour/plugin_selector.cc:58 +msgid "To be added" +msgstr "A serem acrescentados" + +#: gtk_ardour/plugin_selector.cc:72 +msgid "ardour: plugins" +msgstr "ardour: efeitos/plug-ins" + +#: gtk_ardour/plugin_selector.cc:82 +msgid "Add a plugin to the effect list" +msgstr "Acrescentar à lista de efeitos/plug-ins" + +#: gtk_ardour/plugin_selector.cc:84 +msgid "Remove a plugin from the effect list" +msgstr "Remover à lista de efeitos/plug-ins" + +#: gtk_ardour/plugin_selector.cc:88 +msgid "Update" +msgstr "Actualizar" + +#: gtk_ardour/plugin_selector.cc:89 +msgid "Update available plugins" +msgstr "Actualizar efeitos/plug-ins disponíveis" + +#: gtk_ardour/plugin_selector.cc:110 +msgid "LADSPA" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:113 +msgid "VST" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:83 +msgid "" +"unknown type of editor-supplying plugin (note: no VST support in this " +"version of ardour)" +msgstr "" +"tipo desconhecido de editor de efeito/plug-in (nota: esta versão do ardour " +"não suporta VST)" + +#: gtk_ardour/plugin_ui.cc:269 +msgid "Plugin Editor: could not build control element for port %1" +msgstr "" +"Editor de efeitos/plug-ins: não foi possível criar elemento de controlo para " +"%1" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "in" +msgstr "entrada" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "ins" +msgstr "entradas" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "out" +msgstr "saída" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "outs" +msgstr "saídas" + +#: gtk_ardour/plugin_ui.cc:382 +msgid "automation control" +msgstr "controlo de automatização" + +#: gtk_ardour/plugin_ui.cc:869 +msgid "save" +msgstr "guardar" + +#: gtk_ardour/plugin_ui.cc:870 +msgid "bypass" +msgstr "ignorar" + +#: gtk_ardour/plugin_ui.cc:892 +msgid "Plugin preset %1 not found" +msgstr "Parametrização de efeito/plug-in %1 inexistente" + +#: gtk_ardour/plugin_ui.cc:903 +msgid "Name for plugin settings:" +msgstr "Nome para efeito/plug-in:" + +#: gtk_ardour/redirect_automation_line.cc:53 +msgid "redirect automation created for non-plugin" +msgstr "automatização de re-encaminhamento criado para um não-efeito/plug-in" + +#: gtk_ardour/redirect_automation_time_axis.cc:92 +msgid "add automation event to " +msgstr "acrescentar evento de automatização a " + +#: gtk_ardour/redirect_box.cc:213 +msgid "New send" +msgstr "" + +#: gtk_ardour/redirect_box.cc:214 +#, fuzzy +msgid "Show send controls" +msgstr "Controlo de velocidade" + +#: gtk_ardour/redirect_box.cc:360 +msgid "New Plugin ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:361 +#, fuzzy +msgid "New Insert" +msgstr "nova entrada" + +#: gtk_ardour/redirect_box.cc:362 +msgid "New Send ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:380 +#, fuzzy +msgid "Select all" +msgstr "Seleccionar tudo" + +#: gtk_ardour/redirect_box.cc:381 +#, fuzzy +msgid "Deselect all" +msgstr "Seleccionar tudo" + +#: gtk_ardour/redirect_box.cc:389 +#, fuzzy +msgid "Inserts" +msgstr "Inverter" + +#: gtk_ardour/redirect_box.cc:390 +#, fuzzy +msgid "Sends" +msgstr "Segundos" + +#: gtk_ardour/redirect_box.cc:393 +#, fuzzy +msgid "Select all ..." +msgstr "Seleccionar tudo" + +#: gtk_ardour/redirect_box.cc:406 +#, fuzzy +msgid "Activate All" +msgstr "Activar" + +#: gtk_ardour/redirect_box.cc:407 +#, fuzzy +msgid "Deactivate All" +msgstr "Desactivar" + +#: gtk_ardour/redirect_box.cc:488 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point, there are\n" +"%3 active signal streams.\n" +"\n" +"This makes no sense - you are throwing away\n" +"part of the signal." +msgstr "" + +#: gtk_ardour/redirect_box.cc:500 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point there are\n" +"only %3 active signal streams.\n" +"\n" +"This makes no sense - unless the plugin supports\n" +"side-chain inputs. A future version of Ardour will\n" +"support this type of configuration." +msgstr "" + +#: gtk_ardour/redirect_box.cc:513 +msgid "" +"You attempted to add a plugin (%1).\n" +"\n" +"The I/O configuration doesn't make sense:\n" +"\n" +"The plugin has %2 inputs and %3 outputs.\n" +"The track/bus has %4 inputs and %5 outputs.\n" +"The insertion point, has %6 active signals.\n" +"\n" +"Ardour does not understand what to do in such situations.\n" +msgstr "" + +#: gtk_ardour/redirect_box.cc:616 +msgid "Pre-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:619 +msgid "Post-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:781 +msgid "" +"You cannot reorder this set of redirects\n" +"in that way because the inputs and\n" +"outputs do not work correctly." +msgstr "" + +#: gtk_ardour/redirect_box.cc:903 +#, fuzzy +msgid "ardour: rename redirect" +msgstr "ardour: renomear região" + +#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043 +msgid "" +"Copying the set of redirects on the clipboard failed,\n" +"probably because the I/O configuration of the plugins\n" +"could not match the configuration of this track." +msgstr "" + +#: gtk_ardour/redirect_box.cc:1064 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this track?\n" +"(this cannot be undone)" +msgstr "" +"Deseja realmente remover o faixa \"%1\" ?\n" +"(esta operação não pode ser desfeita)" + +#: gtk_ardour/redirect_box.cc:1067 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this bus?\n" +"(this cannot be undone)" +msgstr "" +"Deseja realmente remover o faixa \"%1\" ?\n" +"(esta operação não pode ser desfeita)" + +#: gtk_ardour/redirect_box.cc:1071 +#, fuzzy +msgid "Yes, remove them all" +msgstr "Sim, remover." + +#: gtk_ardour/redirect_box.cc:1114 +#, fuzzy +msgid "ardour: %1" +msgstr "ardour: misturador" + +#: gtk_ardour/redirect_box.cc:1156 +#, fuzzy +msgid "ardour: %1: %2 (by %3)" +msgstr "ardour: misturador: " + +#: gtk_ardour/region_editor.cc:43 +msgid "NAME:" +msgstr "NOME:" + +#: gtk_ardour/region_editor.cc:44 +msgid "lock" +msgstr "bloquear" + +#: gtk_ardour/region_editor.cc:46 +msgid "opaque" +msgstr "opaco" + +#: gtk_ardour/region_editor.cc:49 +msgid "Layer" +msgstr "Nível" + +#: gtk_ardour/region_editor.cc:57 +msgid "ENVELOPE" +msgstr "ENVOLVENTE" + +#: gtk_ardour/region_editor.cc:108 +msgid "mute this region" +msgstr "emudecer esta região" + +#: gtk_ardour/region_editor.cc:109 +msgid "regions underneath this one cannot be heard" +msgstr "regiões abaixo desta não serão ouvidas" + +#: gtk_ardour/region_editor.cc:110 +msgid "prevent any changes to this region" +msgstr "evitar qualquer alteração nesta região" + +#: gtk_ardour/region_editor.cc:111 +msgid "use the gain envelope during playback" +msgstr "usar a envolvente de ganho durante a reprodução" + +#: gtk_ardour/region_editor.cc:112 +msgid "show the gain envelope" +msgstr "mostrar a curva de envolvente de ganho" + +#: gtk_ardour/region_editor.cc:113 +msgid "use fade in curve during playback" +msgstr "usar curva de evanescimento durante a reprodução" + +#: gtk_ardour/region_editor.cc:114 +msgid "use fade out curve during playback" +msgstr "usar curva de desvanecimento durante a reprodução" + +#: gtk_ardour/region_editor.cc:115 +msgid "audition this region" +msgstr "ouvir esta região" + +#: gtk_ardour/region_editor.cc:148 +msgid "START:" +msgstr "INÃCIO:" + +#: gtk_ardour/region_editor.cc:150 +msgid "END:" +msgstr "FINAL:" + +#: gtk_ardour/region_editor.cc:152 +msgid "LENGTH:" +msgstr "TAMANHO:" + +#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198 +#: gtk_ardour/region_editor.cc:234 +msgid "active" +msgstr "activo" + +#: gtk_ardour/region_editor.cc:179 +msgid "visible" +msgstr "visível" + +#: gtk_ardour/region_editor.cc:197 +msgid "FADE IN" +msgstr "EVANESCER" + +#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235 +msgid "msecs" +msgstr "msegs" + +#: gtk_ardour/region_editor.cc:233 +msgid "FADE OUT" +msgstr "DESVANECER" + +#: gtk_ardour/region_editor.cc:276 +msgid "ardour: region " +msgstr "ardour: região" + +#: gtk_ardour/region_editor.cc:410 +msgid "fade in edit" +msgstr "alterar evanescimento" + +#: gtk_ardour/region_editor.cc:422 +msgid "fade out edit" +msgstr "alterar desvanecimento" + +#: gtk_ardour/regionview.cc:1169 +#, fuzzy +msgid "add gain control point" +msgstr "remover ponto de controlo" + +#: gtk_ardour/route_params_ui.cc:58 +msgid "Tracks/Buses" +msgstr "Faixas/Barramentos" + +#: gtk_ardour/route_params_ui.cc:59 +msgid "Pre Redirects" +msgstr "Pré-encaminhamentos" + +#: gtk_ardour/route_params_ui.cc:60 +msgid "Post Redirects" +msgstr "Pós-encaminhamentos" + +#: gtk_ardour/route_params_ui.cc:105 +#, fuzzy +msgid "Pre-fader Redirects" +msgstr "Pré-encaminhamentos" + +#: gtk_ardour/route_params_ui.cc:106 +#, fuzzy +msgid "Post-fader Redirects" +msgstr "Pós-encaminhamentos" + +#: gtk_ardour/route_params_ui.cc:138 +#, fuzzy +msgid "ardour: track/bus inspector" +msgstr "ardour: acrescentar faixa/barramento" + +#: gtk_ardour/route_params_ui.cc:139 +msgid "ardour_route_parameters" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:189 +msgid "route display list item for renamed route not found!" +msgstr "não foi encontrado qualquer elemento de encaminhamento" + +#: gtk_ardour/route_params_ui.cc:448 +msgid "NO TRACK" +msgstr "SEM FAIXA" + +#: gtk_ardour/route_params_ui.cc:669 +#, fuzzy +msgid "ardour: track/bus inspector: " +msgstr "ardour: acrescentar faixa/barramento" + +#: gtk_ardour/route_params_ui.cc:673 +msgid "No Route Selected" +msgstr "Caminho Não Seleccionado" + +#: gtk_ardour/route_params_ui.cc:674 +#, fuzzy +msgid "ardour: track/bus/inspector: no route selected" +msgstr "ardour: parâmetros de encaminhamento: caminho não seleccionado" + +#: gtk_ardour/route_ui.cc:134 +msgid "mute change" +msgstr "mudo alterado" + +#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220 +msgid "solo change" +msgstr "solo alterado" + +#: gtk_ardour/route_ui.cc:284 +msgid "rec-enable change" +msgstr "gravar alterado" + +#: gtk_ardour/route_ui.cc:423 +msgid "Solo-safe" +msgstr "solo livre" + +#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474 +msgid "MIDI Bind" +msgstr "Associação MIDI" + +#: gtk_ardour/route_ui.cc:445 +msgid "Pre Fader" +msgstr "Pré-Atenuador" + +#: gtk_ardour/route_ui.cc:452 +msgid "Post Fader" +msgstr "Pós-Atenuador" + +#: gtk_ardour/route_ui.cc:459 +msgid "Control Outs" +msgstr "Saídas de Controlo" + +#: gtk_ardour/route_ui.cc:466 +msgid "Main Outs" +msgstr "Saídas Principais" + +#: gtk_ardour/route_ui.cc:503 +msgid "mix group solo change" +msgstr "grupo solo alterado" + +#: gtk_ardour/route_ui.cc:537 +msgid "mix group mute change" +msgstr "grupo mudo alterado" + +#: gtk_ardour/route_ui.cc:553 +msgid "mix group rec-enable change" +msgstr "grupo gravar alterado" + +#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258 +msgid "ardour: color selection" +msgstr "ardor: selecção de cor" + +#: gtk_ardour/route_ui.cc:652 +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"You may also lose the playlist used by this track.\n" +"(cannot be undone)" +msgstr "" +"Deseja realmente remover o faixa \"%1\" ?\n" +"A lista de reprodução em uso por esta faixa pode ficar perdida.\n" +"(esta operação não pode ser desfeita)" + +#: gtk_ardour/route_ui.cc:654 +msgid "" +"Do you really want to remove bus \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Deseja realmente remover o barramento \"%1\" ?\n" +"(esta operação não pode ser desfeita)" + +#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299 +msgid "Yes, remove it." +msgstr "Sim, remover." + +#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358 +msgid "new name: " +msgstr "novo nome: " + +#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31 +msgid "Beats per minute" +msgstr "Batimentos por minuto" + +#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35 +#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163 +msgid "Beat" +msgstr "Batimento" + +#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158 +msgid "Meter denominator" +msgstr "Denominador métrico" + +#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159 +msgid "Beats per bar" +msgstr "Batimentos por compasso" + +#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189 +msgid "whole (1)" +msgstr "toda (1)" + +#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191 +msgid "second (2)" +msgstr "segunda (2)" + +#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193 +msgid "third (3)" +msgstr "terça (3)" + +#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195 +#: gtk_ardour/tempo_dialog.cc:203 +msgid "quarter (4)" +msgstr "quarta (4)" + +#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197 +msgid "eighth (8)" +msgstr "octogésima (8)" + +#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199 +msgid "sixteenth (16)" +msgstr "hexodécima (16)" + +#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201 +msgid "thirty-second (32)" +msgstr "trigésima-segunda (32)" + +#: gtk_ardour/tempo_dialog.cc:301 +msgid "garbaged note type entry (%1)" +msgstr "tipo de nota desconhecido (%1)" + +#: gtk_ardour/tempo_dialog.cc:311 +msgid "incomprehensible note type entry (%1)" +msgstr "tipo de nota imcompreensível (%1)" + +#: gtk_ardour/time_axis_view.cc:95 +msgid "gTortnam" +msgstr "" + +#: gtk_ardour/time_axis_view.cc:446 +msgid "Largest" +msgstr "Enorme" + +#: gtk_ardour/time_axis_view.cc:447 +msgid "Large" +msgstr "Grande" + +#: gtk_ardour/time_axis_view.cc:448 +msgid "Larger" +msgstr "Maior" + +#: gtk_ardour/time_axis_view.cc:450 +msgid "Smaller" +msgstr "Menor" + +#: gtk_ardour/time_axis_view.cc:451 +msgid "Small" +msgstr "Pequeno" + +#: gtk_ardour/time_axis_view.cc:785 +msgid "unknown track height name \"%1\" in XML GUI information" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:69 +msgid "TimeAxisViewItemName" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:258 +msgid "new duration %1 frames is out of bounds for %2" +msgstr "" + +#: gtk_ardour/time_selection.cc:40 +msgid "programming error: request for non-existent audio range (%1)!" +msgstr "" + +#: gtk_ardour/utils.cc:57 +msgid "" +"\"\n" +"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+=" +msgstr "" + +#: gtk_ardour/utils.cc:66 +msgid "aeiou" +msgstr "" + +#: gtk_ardour/utils.cc:75 +msgid "AEIOU" +msgstr "" + +#: gtk_ardour/utils.cc:84 +msgid "bcdfghjklmnpqrtvwxyz" +msgstr "" + +#: gtk_ardour/utils.cc:93 +msgid "BCDFGHJKLMNPQRTVWXYZ" +msgstr "" + +#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265 +msgid "bad XPM header %1" +msgstr "" + +#: gtk_ardour/utils.cc:516 +msgid "missing RGBA style for \"%1\"" +msgstr "" + +#: gtk_ardour/visual_time_axis.cc:297 +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Deseja realmente remover o faixa \"%1\" ?\n" +"(esta operação não pode ser desfeita)" + +#: gtk_ardour/visual_time_axis.cc:385 +msgid "A track already exists with that name" +msgstr "Já existe uma faixa com este nome" + +#~ msgid "Seamless Looping" +#~ msgstr "Ciclos Imperceptíveis" + +#~ msgid "Export to CD" +#~ msgstr "Exportar para CD" + +#~ msgid "Recieve MMC" +#~ msgstr "Receber MMC" + +#~ msgid "Trace MIDI Input" +#~ msgstr "Rastrear entradas MIDI" + +#~ msgid "Trace MIDI Output" +#~ msgstr "Rastrear saídas MIDI" + +#~ msgid "MTC Port" +#~ msgstr "Porta MTC" + +#~ msgid "MIDI Param Port" +#~ msgstr "Porta Parameterização MIDI" + +#~ msgid "attempt to timestretch a non-audio track!" +#~ msgstr "tentativa de alongamento temporal duma faixa não-audio" + +#~ msgid "move region(s) between tracks" +#~ msgstr "Mover regiões entre faixas" + +#~ msgid "copy region(s) between tracks" +#~ msgstr "Copiar regiões entre faixas" + +#~ msgid "ardour: tempo editor" +#~ msgstr "ardour: edição de tempo" + +#~ msgid "apply" +#~ msgstr "aplicar" + +#~ msgid "fade" +#~ msgstr "desvanecimento" + +#~ msgid "Edit left" +#~ msgstr "Editar à esquerda" + +#~ msgid "Edit right" +#~ msgstr "Editar à direita" + +#~ msgid "Edit fade" +#~ msgstr "Editar desvanecimento" + +#~ msgid "Export region" +#~ msgstr "Exportar região" + +#, fuzzy +#~ msgid "Bounce region" +#~ msgstr "Rebater selecção" + +#~ msgid "Region" +#~ msgstr "Região" + +#~ msgid "Play selected region" +#~ msgstr "Reproduzir região seleccionada" + +#~ msgid "clear connections" +#~ msgstr "apagar ligações" + +#~ msgid "add comments/notes here" +#~ msgstr "acrescentar comentários/notas aqui" + +#~ msgid "Crossfades in use" +#~ msgstr "Desvanecimentos cruzados automáticos em utilização" + +#~ msgid "outside this computer" +#~ msgstr "fora deste computador" + +#~ msgid "inside this computer" +#~ msgstr "dentro deste computador" + +#~ msgid "Recorded audio is generated" +#~ msgstr "Gravação audio é gerada" diff --git a/gtk2_ardour/po/ru_RU.po b/gtk2_ardour/po/ru_RU.po new file mode 100644 index 0000000000..b4de6dcce9 --- /dev/null +++ b/gtk2_ardour/po/ru_RU.po @@ -0,0 +1,5178 @@ +# Copyright (C) 2004 Paul Davis +# This file is distributed under the same license as the gtk-ardour package. +# Igor Blinov pitstop@nm.ru, 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: gtk-ardour 0.413.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2005-09-19 18:09-0400\n" +"PO-Revision-Date: 2004-03-31 00:45+0300\n" +"Last-Translator: Igor Blinov pitstop@nm.ru\n" +"Language-Team: Russian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: gtk_ardour/about.cc:134 +msgid "Marcus Andersson" +msgstr "" + +#: gtk_ardour/about.cc:135 +msgid "Jeremy Hall" +msgstr "" + +#: gtk_ardour/about.cc:136 +msgid "Steve Harris" +msgstr "" + +#: gtk_ardour/about.cc:137 +msgid "Tim Mayberry" +msgstr "" + +#: gtk_ardour/about.cc:138 +msgid "Mark Stewart" +msgstr "" + +#: gtk_ardour/about.cc:139 +msgid "Sam Chessman" +msgstr "" + +#: gtk_ardour/about.cc:140 +msgid "Jack O'Quin" +msgstr "" + +#: gtk_ardour/about.cc:141 +msgid "Matt Krai" +msgstr "" + +#: gtk_ardour/about.cc:142 +msgid "Ben Bell" +msgstr "" + +#: gtk_ardour/about.cc:143 +msgid "Gerard van Dongen" +msgstr "" + +#: gtk_ardour/about.cc:144 +msgid "Thomas Charbonnel" +msgstr "" + +#: gtk_ardour/about.cc:145 +msgid "Nick Mainsbridge" +msgstr "" + +#: gtk_ardour/about.cc:146 +msgid "Colin Law" +msgstr "" + +#: gtk_ardour/about.cc:147 +msgid "Sampo Savolainen" +msgstr "" + +#: gtk_ardour/about.cc:148 +msgid "Joshua Leach" +msgstr "" + +#: gtk_ardour/about.cc:149 +msgid "Rob Holland" +msgstr "" + +#: gtk_ardour/about.cc:150 +msgid "Per Sigmond" +msgstr "" + +#: gtk_ardour/about.cc:151 +msgid "Doug Mclain" +msgstr "" + +#: gtk_ardour/about.cc:156 +msgid "" +"French:\n" +"\tAlain Fréhel " +msgstr "" + +#: gtk_ardour/about.cc:157 +msgid "" +"German:\n" +"\tKarsten Petersen " +msgstr "" + +#: gtk_ardour/about.cc:158 +msgid "" +"Italian:\n" +"\tFilippo Pappalardo " +msgstr "" + +#: gtk_ardour/about.cc:159 +msgid "" +"Portuguese:\n" +"\tRui Nuno Capela " +msgstr "" + +#: gtk_ardour/about.cc:160 +msgid "" +"Brazilian Portuguese:\n" +"\tAlexander da Franca Fernandes \n" +"\tChris Ross " +msgstr "" + +#: gtk_ardour/about.cc:162 +msgid "" +"Spanish:\n" +"\t Alex Krohn " +msgstr "" + +#: gtk_ardour/about.cc:163 +msgid "" +"Russian:\n" +"\t Igor Blinov " +msgstr "" + +#: gtk_ardour/about.cc:181 +msgid "" +"Copyright (C) 1999-2005 Paul Davis\n" +"Ardour comes with ABSOLUTELY NO WARRANTY\n" +"This is free software, and you are welcome to redistribute it\n" +"under certain conditions; see the file COPYING for details.\n" +msgstr "" + +#: gtk_ardour/about.cc:188 +msgid "" +"Ardour: %1\n" +"(built with ardour/gtk %2.%3.%4 libardour: %5.%6.%7)" +msgstr "" + +#: gtk_ardour/about.cc:206 +msgid "" +"Primary author:\n" +"\tPaul Davis\n" +"\n" +"Major developers:\n" +"\tJesse Chappell\n" +"\tTaybin Rutkin\n" +"Contributors:\n" +"\t" +msgstr "" + +#: gtk_ardour/about.cc:243 +msgid "Authors" +msgstr "" + +#: gtk_ardour/about.cc:244 +#, fuzzy +msgid "Translators" +msgstr "Triangular" + +#: gtk_ardour/about.cc:361 +msgid "cannot open splash image file \"%1\"" +msgstr "не удалоÑÑŒ отобразить заÑтавку (файл \"%1\")" + +#: gtk_ardour/add_route_dialog.cc:40 gtk_ardour/ardour_message.cc:33 +#: gtk_ardour/ardour_ui.cc:2984 gtk_ardour/connection_editor.cc:81 +#: gtk_ardour/crossfade_edit.cc:73 gtk_ardour/editor.cc:3977 +#: gtk_ardour/editor_markers.cc:732 gtk_ardour/editor_ops.cc:1737 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +#: gtk_ardour/main.cc:291 gtk_ardour/plugin_selector.cc:85 +#: gtk_ardour/redirect_box.cc:480 gtk_ardour/redirect_box.cc:777 +#: gtk_ardour/redirect_box.cc:900 +msgid "OK" +msgstr "ОК" + +#: gtk_ardour/add_route_dialog.cc:41 gtk_ardour/add_route_dialog.cc:92 +#: gtk_ardour/add_route_dialog.cc:93 gtk_ardour/ardour_ui.cc:3046 +#: gtk_ardour/connection_editor.cc:55 gtk_ardour/crossfade_edit.cc:72 +#: gtk_ardour/editor.cc:3978 gtk_ardour/editor.cc:3982 +#: gtk_ardour/editor.cc:3983 gtk_ardour/editor_markers.cc:733 +#: gtk_ardour/editor_ops.cc:1738 gtk_ardour/editor_ops.cc:2000 +#: gtk_ardour/editor_timefx.cc:52 gtk_ardour/export_dialog.cc:1129 +#: gtk_ardour/io_selector.cc:55 gtk_ardour/io_selector.cc:785 +#: gtk_ardour/library_ui.cc:722 gtk_ardour/plugin_selector.cc:86 +#: gtk_ardour/redirect_box.cc:901 gtk_ardour/redirect_box.cc:1072 +#: gtk_ardour/tempo_dialog.cc:16 gtk_ardour/tempo_dialog.cc:33 +#: gtk_ardour/tempo_dialog.cc:143 gtk_ardour/tempo_dialog.cc:161 +msgid "Cancel" +msgstr "Отмена" + +#: gtk_ardour/add_route_dialog.cc:42 gtk_ardour/editor.cc:94 +msgid "Tracks" +msgstr "Треки" + +#: gtk_ardour/add_route_dialog.cc:43 +msgid "Busses" +msgstr "Шины" + +#: gtk_ardour/add_route_dialog.cc:48 +msgid "ardour: add track/bus" +msgstr "ardour: добавить трек/шину" + +#: gtk_ardour/add_route_dialog.cc:66 gtk_ardour/plugin_selector.cc:81 +msgid "Add" +msgstr "Добавить" + +#: gtk_ardour/add_route_dialog.cc:86 +msgid "Name (template)" +msgstr "Ð˜Ð¼Ñ (шаблона)" + +#: gtk_ardour/ardour_ui.cc:798 +msgid "" +"pre\n" +"roll" +msgstr "откат" + +#: gtk_ardour/ardour_ui.cc:799 +msgid "" +"post\n" +"roll" +msgstr "накат" + +#: gtk_ardour/ardour_ui.cc:807 +msgid "% " +msgstr "% " + +#: gtk_ardour/ardour_ui.cc:808 +msgid "spring" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:810 +msgid "" +"punch\n" +"in" +msgstr "" +"врезка\n" +"до" + +#: gtk_ardour/ardour_ui.cc:811 +msgid "" +"punch\n" +"out" +msgstr "" +"врезка\n" +"поÑле" + +#: gtk_ardour/ardour_ui.cc:812 +msgid "" +"auto\n" +"return" +msgstr "" +"авто\n" +"возврат" + +#: gtk_ardour/ardour_ui.cc:813 +msgid "" +"auto\n" +"play" +msgstr "" +"авто\n" +"воÑпр." + +#: gtk_ardour/ardour_ui.cc:814 +msgid "" +"auto\n" +"input" +msgstr "" +"авто\n" +"вход" + +#: gtk_ardour/ardour_ui.cc:815 +msgid "click" +msgstr "метроном" + +#: gtk_ardour/ardour_ui.cc:816 +msgid "" +"follow\n" +"PH" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:817 +msgid "AUDITIONING" +msgstr "КОÐТРОЛЬ" + +#: gtk_ardour/ardour_ui.cc:818 +msgid "SOLO" +msgstr "СОЛО" + +#: gtk_ardour/ardour_ui.cc:870 +msgid "Percentage" +msgstr "Процентов" + +#: gtk_ardour/ardour_ui.cc:872 +msgid "Semitones" +msgstr "Полутонов" + +#: gtk_ardour/ardour_ui.cc:875 +msgid "Sprung" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:877 +msgid "Wheel" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:902 +msgid "" +"You cannot record-enable\n" +"track %1\n" +"because it has no input connections.\n" +"You would be wasting space recording silence." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1073 +msgid "quit" +msgstr "выйти" + +#: gtk_ardour/ardour_ui.cc:1082 +msgid "" +"Ardour was unable to save your session.\n" +"\n" +"If you still wish to quit, please use the\n" +"\n" +"\"Just quit\" option." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1107 +msgid "Save and %1" +msgstr "Сохранить и %1" + +#: gtk_ardour/ardour_ui.cc:1112 +msgid "Just %1" +msgstr "Да, %1" + +#: gtk_ardour/ardour_ui.cc:1117 +msgid "Don't %1" +msgstr "Отмена" + +#: gtk_ardour/ardour_ui.cc:1126 +#, fuzzy +msgid "session" +msgstr "СеÑÑиÑ" + +#: gtk_ardour/ardour_ui.cc:1128 +#, fuzzy +msgid "snapshot" +msgstr "Снимок" + +#: gtk_ardour/ardour_ui.cc:1130 +#, fuzzy +msgid "" +"The %1\n" +"\"%2\"\n" +"has not been saved.\n" +"\n" +"Any changes made this time\n" +"will be lost unless you save it.\n" +"\n" +"What do you want to do?" +msgstr "" +"СеÑÑÐ¸Ñ \"%1\"\n" +"не Ñохранена.\n" +"\n" +"Ð’Ñе Ñделанные изменениÑ\n" +"будут потерÑны, еÑли не Ñохранить их.\n" +"\n" +"Что Ð’Ñ‹ хотите Ñделать?" + +#: gtk_ardour/ardour_ui.cc:1151 +msgid "Prompter" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1152 +msgid "ardour: save session?" +msgstr "ardour: Ñохранить ÑеÑÑию?" + +#: gtk_ardour/ardour_ui.cc:1219 +#, fuzzy, c-format +msgid "disconnected" +msgstr "ОтÑоединить" + +#: gtk_ardour/ardour_ui.cc:1226 +#, fuzzy, c-format +msgid "SR: %.1f kHz / %4.1f msecs" +msgstr "SR: %.1f кГц" + +#: gtk_ardour/ardour_ui.cc:1230 +#, c-format +msgid "SR: %u kHz / %4.1f msecs" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:1243 +#, c-format +msgid "DSP Load: %.1f%%" +msgstr "Загрузка DSP: %.1f%%" + +#: gtk_ardour/ardour_ui.cc:1253 +#, c-format +msgid "Disk r:%5.1f w:%5.1f MB/s" +msgstr "ДиÑк r:%5.1f w:%5.1f MB/Ñек" + +#: gtk_ardour/ardour_ui.cc:1267 +#, fuzzy, c-format +msgid "Buffers p:%%% c:%%%" +msgstr "Буферы p:%5.0f%% c:%5.0f%%" + +#: gtk_ardour/ardour_ui.cc:1294 +msgid "space: 24hrs+" +msgstr "меÑто на диÑке: 24 чаÑа +" + +#: gtk_ardour/ardour_ui.cc:1324 +#, c-format +msgid "space: %02dh:%02dm:%02ds" +msgstr "Ñвободное меÑто: %02dч:%02dмин:%02dÑек" + +#: gtk_ardour/ardour_ui.cc:1575 +msgid "programming error: impossible control method" +msgstr "ошибка в программе: impossible control method" + +#: gtk_ardour/ardour_ui.cc:1800 +msgid "cancel" +msgstr "отмена" + +#: gtk_ardour/ardour_ui.cc:1801 +msgid "rescan" +msgstr "обновить" + +#: gtk_ardour/ardour_ui.cc:1842 +msgid "open session" +msgstr "открыть ÑеÑÑию" + +#: gtk_ardour/ardour_ui.cc:1897 +msgid "Patience is a virtue.\n" +msgstr "По нитке дойдёшь и до клубка.\n" + +#: gtk_ardour/ardour_ui.cc:1906 +msgid "You cannot add a track without a session already loaded." +msgstr "Ð’Ñ‹ не можете добавить трек пока ÑеÑÑÐ¸Ñ Ð½Ðµ загружена." + +#: gtk_ardour/ardour_ui.cc:1913 +msgid "could not create new audio track" +msgstr "не удалоÑÑŒ Ñоздать новый аудиотрек" + +#: gtk_ardour/ardour_ui.cc:1917 +msgid "could not create new audio bus" +msgstr "не удалоÑÑŒ Ñоздать новую аудиошину" + +#: gtk_ardour/ardour_ui.cc:1936 +msgid "" +"There are insufficient JACK ports available\n" +"to create a new track or bus.\n" +"You should save Ardour, exit and\n" +"restart JACK with more ports." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2071 +msgid "" +"Please create 1 or more track\n" +"before trying to record.\n" +"Check the Session menu." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2312 +#, fuzzy +msgid "" +"JACK has either been shutdown or it\n" +"disconnected Ardour because Ardour\n" +"was not fast enough. You can save the\n" +"session and/or try to reconnect to JACK ." +msgstr "" +"Внимание! JACK завершил работу или\n" +"потерÑл Ñинхронизацию Ñ Ardour и отÑоединил его.\n" +"Ðеобходимо Ñохранить ÑеÑÑию и\n" +"перезапуÑтить JACK и Ardour." + +#: gtk_ardour/ardour_ui.cc:2328 +msgid "Unable to create all required ports" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2336 +#, fuzzy +msgid "Unable to start the session running" +msgstr "Ð’ начало ÑеÑÑии" + +#: gtk_ardour/ardour_ui.cc:2472 +msgid "No Stream" +msgstr "Ðет потока" + +#: gtk_ardour/ardour_ui.cc:2499 gtk_ardour/ardour_ui.cc:2518 +msgid "none" +msgstr "нет" + +#: gtk_ardour/ardour_ui.cc:2508 gtk_ardour/ardour_ui.cc:2527 +#: gtk_ardour/automation_time_axis.cc:189 +#: gtk_ardour/automation_time_axis.cc:218 +#: gtk_ardour/automation_time_axis.cc:458 gtk_ardour/mixer_strip.cc:211 +#: gtk_ardour/mixer_strip.cc:223 gtk_ardour/mixer_strip.cc:947 +#: gtk_ardour/plugin_ui.cc:416 gtk_ardour/plugin_ui.cc:659 +msgid "off" +msgstr "выкл" + +#: gtk_ardour/ardour_ui.cc:2548 +msgid "Name for snapshot" +msgstr "Ð˜Ð¼Ñ Ñнимка" + +#: gtk_ardour/ardour_ui.cc:2716 gtk_ardour/new_session_dialog.cc:294 +msgid "Name for mix template:" +msgstr "Ð˜Ð¼Ñ mix-шаблона:" + +#: gtk_ardour/ardour_ui.cc:2717 +msgid "-template" +msgstr "-шаблон" + +#: gtk_ardour/ardour_ui.cc:2760 +msgid "Session %1 already exists at %2" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2832 +msgid "" +"You do not have write access to this session.\n" +"This prevents the session from being loaded." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2844 gtk_ardour/ardour_ui.cc:2897 +msgid "Session \"%1 (snapshot %2)\" did not load successfully" +msgstr "Ðе удалоÑÑŒ загрузить ÑеÑÑию \"%1 (Ñнимок %2)\"" + +#: gtk_ardour/ardour_ui.cc:2966 +msgid "" +"No audio files were ready for cleanup\n" +"\n" +"If this seems suprising, check for any existing\n" +"snapshots. These may still include regions that\n" +"require some unused files to continue to exist." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2995 gtk_ardour/ardour_ui.cc:3001 +msgid "files" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:2997 gtk_ardour/ardour_ui.cc:3003 +msgid "file" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3026 +msgid "ardour: cleanup" +msgstr "ardour: очиÑтка" + +#: gtk_ardour/ardour_ui.cc:3040 +msgid "" +"Cleanup is a destructive operation.\n" +"ALL undo/redo information will be lost if you cleanup.\n" +"Unused audio files will be moved to a \"dead sounds\" location." +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3045 +msgid "Proceed with cleanup" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3061 +#, fuzzy +msgid "CleanupDialog" +msgstr "ОчиÑтка" + +#: gtk_ardour/ardour_ui.cc:3062 +#, fuzzy +msgid "ardour cleanup" +msgstr "ardour: очиÑтка" + +#: gtk_ardour/ardour_ui.cc:3063 +#, fuzzy +msgid "ardour_cleanup" +msgstr "ardour: очиÑтка" + +#: gtk_ardour/ardour_ui.cc:3086 +msgid "cleaned files" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3087 +#, fuzzy +msgid "" +"The following %1 %2 were not in use.\n" +"The next time you flush the wastebasket\n" +"it will release an additional %3 %4bytes\n" +"of disk space" +msgstr "" +"Следующие %1 файлов не иÑпользуютÑÑ.\n" +"ПоÑÐ»ÐµÐ´ÑƒÑŽÑ‰Ð°Ñ Ð¾Ñ‡Ð¸Ñтка корзины оÑвободит\n" +"%2 мегабайт меÑта на диÑке." + +#: gtk_ardour/ardour_ui.cc:3110 +#, fuzzy +msgid "deleted file" +msgstr "удалённые файлы" + +#: gtk_ardour/ardour_ui.cc:3111 +#, fuzzy +msgid "" +"The following %1 file%2 were deleted, releasing %3 %4bytes of disk space" +msgstr "" +"Следующие %1 файлов были удалены, оÑвободив при Ñтом %2 Мб меÑта на диÑке" + +#: gtk_ardour/ardour_ui.cc:3226 +msgid "Recording was stopped because your system could not keep up." +msgstr "ЗапиÑÑŒ оÑтановлена из-за недоÑтаточного быÑтродейÑÑ‚Ð²Ð¸Ñ ÑиÑтемы" + +#: gtk_ardour/ardour_ui.cc:3248 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to write data to disk\n" +"quickly enough to keep up with recording.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3266 +msgid "" +"The disk system on your computer\n" +"was not able to keep up with Ardour.\n" +"\n" +"Specifically, it failed to read data from disk\n" +"quickly enough to keep up with playback.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3291 +msgid "Recover from crash" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3292 +msgid "Ignore crash data" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3293 +msgid "" +"This session appears to have been in\n" +"middle of recording when ardour or\n" +"the computer was shutdown.\n" +"\n" +"Ardour can recover any captured audio for\n" +"you, or it can ignore it. Please decide\n" +"what you would like to do.\n" +msgstr "" + +#: gtk_ardour/ardour_ui.cc:3338 +#, fuzzy +msgid "Could not disconnect from JACK" +msgstr "Ðе удалоÑÑŒ ÑоединитьÑÑ Ñ Ñервером JACK как \"%1\"" + +#: gtk_ardour/ardour_ui.cc:3351 +#, fuzzy +msgid "Could not reconnect to JACK" +msgstr "Ðе удалоÑÑŒ ÑоединитьÑÑ Ñ Ñервером JACK как \"%1\"" + +#: gtk_ardour/ardour_ui2.cc:60 +msgid "UI: cannot setup editor" +msgstr "ИнтерфейÑ: не удалоÑÑŒ инициализировать редактор" + +#: gtk_ardour/ardour_ui2.cc:65 +msgid "UI: cannot setup mixer" +msgstr "ИнтерфейÑ: не удалоÑÑŒ инициализировать микшер" + +#: gtk_ardour/ardour_ui2.cc:70 +msgid "UI: cannot setup meter_bridge" +msgstr "ИнтерфейÑ: не удалоÑÑŒ инициализировать индикаторы" + +#: gtk_ardour/ardour_ui2.cc:98 +msgid "MMC + Local" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:99 +msgid "MMC" +msgstr "MMC" + +#: gtk_ardour/ardour_ui2.cc:100 +msgid "Local" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:117 +msgid "MMC ID" +msgstr "MMC идентификатор" + +#: gtk_ardour/ardour_ui2.cc:215 +msgid "Play from playhead" +msgstr "ВоÑпроизвеÑти от указателÑ" + +#: gtk_ardour/ardour_ui2.cc:216 +msgid "Stop playback" +msgstr "Стоп" + +#: gtk_ardour/ardour_ui2.cc:217 +#, fuzzy +msgid "Play range/selection" +msgstr "ВоÑпроизвеÑти выделенное" + +#: gtk_ardour/ardour_ui2.cc:218 +msgid "Go to start of session" +msgstr "Ð’ начало ÑеÑÑии" + +#: gtk_ardour/ardour_ui2.cc:219 +msgid "Go to end of session" +msgstr "Ð’ конец ÑеÑÑии" + +#: gtk_ardour/ardour_ui2.cc:220 +msgid "Play loop range" +msgstr "ВоÑпроизвеÑти \"кольцо\"" + +#: gtk_ardour/ardour_ui2.cc:221 +msgid "Return to last playback start when stopped" +msgstr "ВернутьÑÑ Ðº точке начала воÑпроизведениÑ" + +#: gtk_ardour/ardour_ui2.cc:222 +msgid "Start playback after any locate" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:223 +msgid "Be sensible about input monitoring" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:224 +msgid "Start recording at auto-punch start" +msgstr "Ðачать запиÑÑŒ Ñ Ð½Ð°Ñ‡Ð°Ð»Ð° \"авто-врезки\"" + +#: gtk_ardour/ardour_ui2.cc:225 +msgid "Stop recording at auto-punch end" +msgstr "ОÑтановить запиÑÑŒ в конце \"авто-врезки\"" + +#: gtk_ardour/ardour_ui2.cc:226 +msgid "Enable/Disable audio click" +msgstr "Вкл./Выкл. метроном" + +#: gtk_ardour/ardour_ui2.cc:227 +#, fuzzy +msgid "Enable/Disable follow playhead" +msgstr "Разрешить/запретить цикл" + +#: gtk_ardour/ardour_ui2.cc:228 +msgid "Shuttle speed control" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:229 +#, c-format +msgid "Select semitones or %%-age for speed display" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:230 +msgid "Select sprung or wheel behaviour" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:231 +msgid "Current transport speed" +msgstr "ТекщаÑÑ ÑкорÑть транÑпорта" + +#: gtk_ardour/ardour_ui2.cc:312 +msgid "Primary clock" +msgstr "ОÑновной Ñчётчик" + +#: gtk_ardour/ardour_ui2.cc:313 +msgid "secondary clock" +msgstr "дополнительный Ñчётчик" + +#: gtk_ardour/ardour_ui2.cc:365 gtk_ardour/ardour_ui2.cc:751 +#: gtk_ardour/ardour_ui2.cc:770 +msgid "stopped" +msgstr "оÑтановлено" + +#: gtk_ardour/ardour_ui2.cc:431 +msgid "ardour: clock" +msgstr "ardour: Ñчётчик" + +#: gtk_ardour/ardour_ui2.cc:721 +msgid "st" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:731 +msgid "sprung" +msgstr "" + +#: gtk_ardour/ardour_ui2.cc:742 +msgid "wheel" +msgstr "" + +#: gtk_ardour/ardour_ui_dependents.cc:74 +msgid "keyboard_target: error setting binding state: invalid node" +msgstr "" + +#: gtk_ardour/ardour_ui_dialogs.cc:158 +msgid "close session" +msgstr "закрыть ÑеÑÑию" + +#: gtk_ardour/ardour_ui_ed.cc:75 gtk_ardour/audio_time_axis.cc:1895 +msgid "New" +msgstr "Ðовый" + +#: gtk_ardour/ardour_ui_ed.cc:76 +msgid "Open" +msgstr "Открыть" + +#: gtk_ardour/ardour_ui_ed.cc:77 +msgid "Recent" +msgstr "ПоÑледние" + +#: gtk_ardour/ardour_ui_ed.cc:78 gtk_ardour/connection_editor.cc:54 +#: gtk_ardour/io_selector.cc:54 gtk_ardour/io_selector.cc:784 +msgid "Close" +msgstr "Закрыть" + +#: gtk_ardour/ardour_ui_ed.cc:84 gtk_ardour/route_params_ui.cc:488 +msgid "Add Track/Bus" +msgstr "Добавить Трек/Шину" + +#: gtk_ardour/ardour_ui_ed.cc:99 +msgid "Connect" +msgstr "Соединить" + +#: gtk_ardour/ardour_ui_ed.cc:100 +msgid "Image Compositor" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:114 +msgid "Save" +msgstr "Сохранить" + +#: gtk_ardour/ardour_ui_ed.cc:118 +msgid "Snapshot" +msgstr "Снимок" + +#: gtk_ardour/ardour_ui_ed.cc:126 +msgid "Save Template..." +msgstr "Сохранить шаблон..." + +#: gtk_ardour/ardour_ui_ed.cc:133 +msgid "Export session to audiofile..." +msgstr "ЭкÑпорт ÑеÑÑии в аудиофайл..." + +#: gtk_ardour/ardour_ui_ed.cc:134 +#, fuzzy +msgid "Export range to audiofile..." +msgstr "ЭкÑпорт ÑеÑÑии в аудиофайл..." + +#: gtk_ardour/ardour_ui_ed.cc:137 gtk_ardour/editor.cc:2312 +#: gtk_ardour/editor.cc:2430 gtk_ardour/export_dialog.cc:118 +#: gtk_ardour/export_dialog.cc:1223 gtk_ardour/export_dialog.cc:1227 +msgid "Export" +msgstr "ЭкÑпорт" + +#: gtk_ardour/ardour_ui_ed.cc:146 +msgid "Cleanup unused sources" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:147 +msgid "Flush wastebasket" +msgstr "ОчиÑтить корзину" + +#: gtk_ardour/ardour_ui_ed.cc:149 +msgid "Cleanup" +msgstr "ОчиÑтка" + +#: gtk_ardour/ardour_ui_ed.cc:154 +msgid "Quit" +msgstr "Выйти" + +#: gtk_ardour/ardour_ui_ed.cc:156 +msgid "Session" +msgstr "СеÑÑиÑ" + +#: gtk_ardour/ardour_ui_ed.cc:162 gtk_ardour/crossfade_edit.cc:287 +#: gtk_ardour/editor.cc:2242 gtk_ardour/editor.cc:2499 +#: gtk_ardour/editor_markers.cc:466 gtk_ardour/mixer_strip.cc:570 +#: gtk_ardour/mixer_strip.cc:629 gtk_ardour/redirect_box.cc:412 +msgid "Edit" +msgstr "Правка" + +#: gtk_ardour/ardour_ui_ed.cc:171 gtk_ardour/mixer_strip.cc:572 +#: gtk_ardour/mixer_strip.cc:631 +msgid "Disconnect" +msgstr "ОтÑоединить" + +#: gtk_ardour/ardour_ui_ed.cc:174 +#, fuzzy +msgid "Reconnect" +msgstr "Соединить" + +#: gtk_ardour/ardour_ui_ed.cc:192 +msgid "Latency" +msgstr "" + +#: gtk_ardour/ardour_ui_ed.cc:195 +msgid "JACK" +msgstr "JACK" + +#: gtk_ardour/ardour_ui_ed.cc:205 +msgid "Editor" +msgstr "Редактор" + +#: gtk_ardour/ardour_ui_ed.cc:206 +msgid "Mixer" +msgstr "Микшер" + +#: gtk_ardour/ardour_ui_ed.cc:212 +msgid "Options Editor" +msgstr "Редактор параметров" + +#: gtk_ardour/ardour_ui_ed.cc:219 +msgid "Audio Library" +msgstr "Ðудио-библиотека" + +#: gtk_ardour/ardour_ui_ed.cc:225 +#, fuzzy +msgid "Track/Bus Inspector" +msgstr "Треки/Шины" + +#: gtk_ardour/ardour_ui_ed.cc:232 +msgid "Connections" +msgstr "СоединениÑ" + +#: gtk_ardour/ardour_ui_ed.cc:240 +msgid "Meter Bridge" +msgstr "Индикаторы" + +#: gtk_ardour/ardour_ui_ed.cc:248 +msgid "Locations" +msgstr "Интервалы" + +#: gtk_ardour/ardour_ui_ed.cc:255 +msgid "Big Clock" +msgstr "Большой Ñчётчик" + +#: gtk_ardour/ardour_ui_ed.cc:261 +msgid "About" +msgstr "О программе" + +#: gtk_ardour/ardour_ui_ed.cc:264 +msgid "Windows" +msgstr "Окна" + +#: gtk_ardour/audio_clock.cc:1640 gtk_ardour/editor.cc:203 +msgid "SMPTE" +msgstr "SMPTE" + +#: gtk_ardour/audio_clock.cc:1641 gtk_ardour/editor.cc:202 +#: gtk_ardour/editor_rulers.cc:359 +msgid "Bars:Beats" +msgstr "Такт:ДолÑ" + +#: gtk_ardour/audio_clock.cc:1642 +msgid "Minutes:Seconds" +msgstr "Минуты:Секунды" + +#: gtk_ardour/audio_clock.cc:1643 +msgid "Audio Frames" +msgstr "Ðудио кадры" + +#: gtk_ardour/audio_clock.cc:1644 gtk_ardour/option_editor.cc:356 +#: gtk_ardour/option_editor.cc:373 gtk_ardour/option_editor.cc:713 +#: gtk_ardour/option_editor.cc:733 gtk_ardour/option_editor.cc:774 +#: gtk_ardour/option_editor.cc:794 +msgid "Off" +msgstr "Выкл" + +#: gtk_ardour/audio_clock.cc:1646 +msgid "Mode" +msgstr "Режим" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:523 +msgid "m" +msgstr "Ñ‚" + +#: gtk_ardour/audio_time_axis.cc:104 gtk_ardour/mixer_strip.cc:524 +msgid "s" +msgstr "Ñ" + +#: gtk_ardour/audio_time_axis.cc:104 +msgid "r" +msgstr "з" + +#: gtk_ardour/audio_time_axis.cc:108 +msgid "g" +msgstr "г" + +#: gtk_ardour/audio_time_axis.cc:109 +msgid "p" +msgstr "Ñп" + +#: gtk_ardour/audio_time_axis.cc:110 gtk_ardour/automation_time_axis.cc:44 +#: gtk_ardour/visual_time_axis.cc:90 +msgid "h" +msgstr "в" + +#: gtk_ardour/audio_time_axis.cc:111 +msgid "a" +msgstr "а" + +#: gtk_ardour/audio_time_axis.cc:112 gtk_ardour/visual_time_axis.cc:89 +msgid "v" +msgstr "п" + +#: gtk_ardour/audio_time_axis.cc:185 +msgid "Record" +msgstr "ЗапиÑÑŒ" + +#: gtk_ardour/audio_time_axis.cc:186 gtk_ardour/option_editor.cc:191 +msgid "Solo" +msgstr "Соло" + +#: gtk_ardour/audio_time_axis.cc:187 gtk_ardour/editor.cc:2236 +#: gtk_ardour/editor.cc:2330 gtk_ardour/panner_ui.cc:433 +msgid "Mute" +msgstr "Тихо" + +#: gtk_ardour/audio_time_axis.cc:188 +msgid "Edit Group" +msgstr "Группы" + +#: gtk_ardour/audio_time_axis.cc:189 gtk_ardour/visual_time_axis.cc:110 +msgid "Display Height" +msgstr "Ð’Ñ‹Ñота дорожки" + +#: gtk_ardour/audio_time_axis.cc:190 +msgid "Playlist" +msgstr "СпиÑок" + +#: gtk_ardour/audio_time_axis.cc:191 gtk_ardour/audio_time_axis.cc:752 +msgid "Automation" +msgstr "Ðвтомат" + +#: gtk_ardour/audio_time_axis.cc:192 gtk_ardour/visual_time_axis.cc:111 +msgid "Visual options" +msgstr "Параметры отображениÑ" + +#: gtk_ardour/audio_time_axis.cc:193 gtk_ardour/visual_time_axis.cc:112 +msgid "Hide this track" +msgstr "Скрыть трек" + +#: gtk_ardour/audio_time_axis.cc:349 +msgid "No group" +msgstr "Ðет группы" + +#: gtk_ardour/audio_time_axis.cc:715 gtk_ardour/automation_time_axis.cc:447 +#: gtk_ardour/imageframe_time_axis.cc:265 gtk_ardour/marker_time_axis.cc:229 +msgid "Height" +msgstr "Ð’Ñ‹Ñота" + +#: gtk_ardour/audio_time_axis.cc:716 gtk_ardour/imageframe_time_axis.cc:266 +#: gtk_ardour/marker_time_axis.cc:230 +msgid "Color" +msgstr "Цвет" + +#: gtk_ardour/audio_time_axis.cc:720 +msgid "Hide all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:721 +msgid "Show all crossfades" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:729 +msgid "show all automation" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:732 +#, fuzzy +msgid "show existing automation" +msgstr "иÑпользовать имеющийÑÑ ÑˆÐ°Ð±Ð»Ð¾Ð½" + +#: gtk_ardour/audio_time_axis.cc:735 +msgid "hide all automation" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:740 gtk_ardour/audio_time_axis.cc:1204 +#: gtk_ardour/editor.cc:234 +msgid "gain" +msgstr "уÑил." + +#: gtk_ardour/audio_time_axis.cc:745 gtk_ardour/audio_time_axis.cc:1244 +msgid "pan" +msgstr "пан." + +#: gtk_ardour/audio_time_axis.cc:750 gtk_ardour/redirect_box.cc:388 +msgid "Plugins" +msgstr "Модули (плагины)" + +#: gtk_ardour/audio_time_axis.cc:758 gtk_ardour/option_editor.cc:95 +msgid "Show waveforms" +msgstr "Отображать форму Ñигнала" + +#: gtk_ardour/audio_time_axis.cc:766 +msgid "Traditional" +msgstr "ОбычнаÑ" + +#: gtk_ardour/audio_time_axis.cc:769 +msgid "Rectified" +msgstr "УвеличеннаÑ" + +#: gtk_ardour/audio_time_axis.cc:772 +msgid "Waveform" +msgstr "Форма Ñигнала" + +#: gtk_ardour/audio_time_axis.cc:782 +#, fuzzy +msgid "align with existing material" +msgstr "СущеÑтвующий материал" + +#: gtk_ardour/audio_time_axis.cc:787 +#, fuzzy +msgid "align with capture time" +msgstr "Ð’Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ð¸Ñи" + +#: gtk_ardour/audio_time_axis.cc:793 +#, fuzzy +msgid "Alignment" +msgstr "ВыровнÑть" + +#: gtk_ardour/audio_time_axis.cc:799 gtk_ardour/mixer_strip.cc:1288 +msgid "Active" +msgstr "Ðктивен" + +#: gtk_ardour/audio_time_axis.cc:804 gtk_ardour/editor.cc:2386 +#: gtk_ardour/editor_markers.cc:454 gtk_ardour/editor_markers.cc:467 +#: gtk_ardour/editor_region_list.cc:400 gtk_ardour/imageframe_time_axis.cc:269 +#: gtk_ardour/location_ui.cc:56 gtk_ardour/marker_time_axis.cc:233 +#: gtk_ardour/mixer_strip.cc:1293 gtk_ardour/plugin_selector.cc:83 +msgid "Remove" +msgstr "Удалить" + +#: gtk_ardour/audio_time_axis.cc:843 gtk_ardour/audio_time_axis.cc:880 +#: gtk_ardour/audio_time_axis.cc:911 +#, fuzzy +msgid "Name for playlist" +msgstr "Ð˜Ð¼Ñ Ñнимка" + +#: gtk_ardour/audio_time_axis.cc:1168 gtk_ardour/visual_time_axis.cc:433 +msgid "a track already exists with that name" +msgstr "трек Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже ÑущеÑтвует" + +#: gtk_ardour/audio_time_axis.cc:1449 gtk_ardour/editor.cc:2001 +#: gtk_ardour/editor_ops.cc:2251 gtk_ardour/selection.cc:539 +msgid "programming error: " +msgstr "ошибка в программе: " + +#: gtk_ardour/audio_time_axis.cc:1889 +msgid "Current: %1" +msgstr "" + +#: gtk_ardour/audio_time_axis.cc:1892 gtk_ardour/editor_markers.cc:452 +#: gtk_ardour/imageframe_time_axis.cc:258 gtk_ardour/marker_time_axis.cc:226 +#: gtk_ardour/mixer_strip.cc:1286 gtk_ardour/redirect_box.cc:377 +msgid "Rename" +msgstr "Переименовать" + +#: gtk_ardour/audio_time_axis.cc:1896 +msgid "New Copy" +msgstr "ÐÐ¾Ð²Ð°Ñ ÐºÐ¾Ð¿Ð¸Ñ" + +#: gtk_ardour/audio_time_axis.cc:1898 +msgid "Clear Current" +msgstr "ОчиÑтить текущий" + +#: gtk_ardour/audio_time_axis.cc:1900 gtk_ardour/editor.cc:2472 +#: gtk_ardour/editor.cc:2557 +msgid "Select" +msgstr "Выделеннное" + +#: gtk_ardour/automation_line.cc:904 +#, fuzzy +msgid "automation event move" +msgstr "автомат" + +#: gtk_ardour/automation_line.cc:906 +#, fuzzy +msgid "automation range drag" +msgstr "автомат" + +#: gtk_ardour/automation_line.cc:1035 gtk_ardour/region_gain_line.cc:64 +#, fuzzy +msgid "remove control point" +msgstr "иÑпользовать контрольные выходы" + +#: gtk_ardour/automation_time_axis.cc:45 gtk_ardour/editor_ops.cc:3010 +msgid "clear" +msgstr "очиÑтить" + +#: gtk_ardour/automation_time_axis.cc:80 +msgid "track height" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:81 +#, fuzzy +msgid "automation state" +msgstr "автомат" + +#: gtk_ardour/automation_time_axis.cc:82 +#, fuzzy +msgid "clear track" +msgstr "Скрыть трек" + +#: gtk_ardour/automation_time_axis.cc:83 +#, fuzzy +msgid "hide track" +msgstr "Скрыть трек" + +#: gtk_ardour/automation_time_axis.cc:191 +#: gtk_ardour/automation_time_axis.cc:229 +#: gtk_ardour/automation_time_axis.cc:462 gtk_ardour/mixer_strip.cc:213 +#: gtk_ardour/mixer_strip.cc:225 gtk_ardour/plugin_ui.cc:419 +#: gtk_ardour/plugin_ui.cc:661 gtk_ardour/region_editor.cc:50 +msgid "play" +msgstr "воÑпроизвеÑти" + +#: gtk_ardour/automation_time_axis.cc:193 +#: gtk_ardour/automation_time_axis.cc:240 +#: gtk_ardour/automation_time_axis.cc:466 gtk_ardour/mixer_strip.cc:215 +#: gtk_ardour/mixer_strip.cc:227 gtk_ardour/plugin_ui.cc:422 +#: gtk_ardour/plugin_ui.cc:663 +msgid "write" +msgstr "запиÑÑŒ" + +#: gtk_ardour/automation_time_axis.cc:195 +#: gtk_ardour/automation_time_axis.cc:251 +#: gtk_ardour/automation_time_axis.cc:470 gtk_ardour/mixer_strip.cc:217 +#: gtk_ardour/mixer_strip.cc:229 gtk_ardour/mixer_strip.cc:953 +#: gtk_ardour/plugin_ui.cc:425 gtk_ardour/plugin_ui.cc:665 +msgid "touch" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:262 gtk_ardour/option_editor.cc:274 +#: gtk_ardour/option_editor.cc:280 gtk_ardour/plugin_ui.cc:428 +msgid "???" +msgstr "" + +#: gtk_ardour/automation_time_axis.cc:276 +#, fuzzy +msgid "clear automation" +msgstr "очиÑтить интервалы" + +#: gtk_ardour/automation_time_axis.cc:449 gtk_ardour/editor_markers.cc:453 +#: gtk_ardour/editor_markers.cc:499 gtk_ardour/editor_region_list.cc:398 +msgid "Hide" +msgstr "Скрыть" + +#: gtk_ardour/automation_time_axis.cc:451 gtk_ardour/connection_editor.cc:52 +#: gtk_ardour/crossfade_edit.cc:76 gtk_ardour/redirect_box.cc:364 +msgid "Clear" +msgstr "ОчиÑтить" + +#: gtk_ardour/automation_time_axis.cc:474 +#, fuzzy +msgid "State" +msgstr "Ðачало" + +#: gtk_ardour/connection_editor.cc:47 gtk_ardour/new_session_dialog.cc:49 +msgid "Input Connections" +msgstr "Входные ÑоединениÑ" + +#: gtk_ardour/connection_editor.cc:48 gtk_ardour/new_session_dialog.cc:48 +msgid "Output Connections" +msgstr "Выходные ÑоединениÑ" + +#: gtk_ardour/connection_editor.cc:49 +#, fuzzy +msgid "New Input" +msgstr "новый вход" + +#: gtk_ardour/connection_editor.cc:50 +#, fuzzy +msgid "New Output" +msgstr "новый выход" + +#: gtk_ardour/connection_editor.cc:51 +#, fuzzy +msgid "Delete" +msgstr "удалить" + +#: gtk_ardour/connection_editor.cc:53 gtk_ardour/connection_editor.cc:96 +#, fuzzy +msgid "Add Port" +msgstr "добавить порт" + +#: gtk_ardour/connection_editor.cc:56 gtk_ardour/connection_editor.cc:105 +#: gtk_ardour/io_selector.cc:56 gtk_ardour/io_selector.cc:786 +#, fuzzy +msgid "Rescan" +msgstr "обновить" + +#: gtk_ardour/connection_editor.cc:101 +msgid "Available Ports" +msgstr "ДоÑтупные порты" + +#: gtk_ardour/connection_editor.cc:183 +msgid "ardour: connections" +msgstr "ardour: ÑоединениÑ" + +#: gtk_ardour/connection_editor.cc:513 +#, c-format +msgid "in %d" +msgstr "в %d" + +#: gtk_ardour/connection_editor.cc:644 +msgid "Name for new connection:" +msgstr "Ð˜Ð¼Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ ÑоединениÑ:" + +#: gtk_ardour/crossfade_edit.cc:71 +#, fuzzy +msgid "crossfade editor" +msgstr "редактировать введение в уровень" + +#: gtk_ardour/crossfade_edit.cc:77 gtk_ardour/panner_ui.cc:449 +#, fuzzy +msgid "Reset" +msgstr "ОгромнаÑ" + +#: gtk_ardour/crossfade_edit.cc:78 +#, fuzzy +msgid "Fade" +msgstr "Затухание" + +#: gtk_ardour/crossfade_edit.cc:79 +#, fuzzy +msgid "Out (dry)" +msgstr "в %d" + +#: gtk_ardour/crossfade_edit.cc:80 +#, fuzzy +msgid "Out" +msgstr "Выходов" + +#: gtk_ardour/crossfade_edit.cc:81 +#, fuzzy +msgid "In (dry)" +msgstr "в %d" + +#: gtk_ardour/crossfade_edit.cc:82 +msgid "In" +msgstr "" + +#: gtk_ardour/crossfade_edit.cc:84 +#, fuzzy +msgid "With Pre-roll" +msgstr "откат" + +#: gtk_ardour/crossfade_edit.cc:85 +#, fuzzy +msgid "With Post-roll" +msgstr "накат" + +#: gtk_ardour/crossfade_edit.cc:93 +#, fuzzy +msgid "Fade In" +msgstr "Затухание" + +#: gtk_ardour/crossfade_edit.cc:94 +#, fuzzy +msgid "Fade Out" +msgstr "Затухание" + +#: gtk_ardour/crossfade_edit.cc:98 +#, fuzzy +msgid "ardour: x-fade edit" +msgstr "ardour: редактор" + +#: gtk_ardour/crossfade_edit.cc:198 gtk_ardour/editor.cc:2311 +#: gtk_ardour/editor_region_list.cc:396 gtk_ardour/option_editor.cc:189 +msgid "Audition" +msgstr "Ðудит" + +#: gtk_ardour/editor.cc:103 gtk_ardour/editor_region_list.cc:804 +msgid "Regions/name" +msgstr "ОблаÑти/имÑ" + +#: gtk_ardour/editor.cc:108 +msgid "Chunks" +msgstr "Фрагменты" + +#: gtk_ardour/editor.cc:116 gtk_ardour/editor.cc:4079 +msgid "Slide" +msgstr "Скольжение" + +#: gtk_ardour/editor.cc:117 gtk_ardour/editor.cc:4077 +msgid "Splice" +msgstr "Стыковка" + +#: gtk_ardour/editor.cc:122 gtk_ardour/editor.cc:4136 +#: gtk_ardour/export_dialog.cc:82 gtk_ardour/export_dialog.cc:96 +#: gtk_ardour/export_dialog.cc:912 gtk_ardour/export_dialog.cc:977 +msgid "None" +msgstr "Ðет" + +#: gtk_ardour/editor.cc:123 gtk_ardour/editor.cc:4124 +#, fuzzy +msgid "CD Frames" +msgstr "Кадр" + +#: gtk_ardour/editor.cc:124 gtk_ardour/editor.cc:4126 +#, fuzzy +msgid "SMPTE Frames" +msgstr "SMPTE Кадры/Секунды" + +#: gtk_ardour/editor.cc:125 gtk_ardour/editor.cc:4128 +#, fuzzy +msgid "SMPTE Seconds" +msgstr "SMPTE Кадры/Секунды" + +#: gtk_ardour/editor.cc:126 gtk_ardour/editor.cc:4130 +msgid "SMPTE Minutes" +msgstr "" + +#: gtk_ardour/editor.cc:127 gtk_ardour/editor.cc:4132 +#, fuzzy +msgid "Seconds" +msgstr "Минуты:Секунды" + +#: gtk_ardour/editor.cc:128 gtk_ardour/editor.cc:4134 +#, fuzzy +msgid "Minutes" +msgstr "Главные выходы" + +#: gtk_ardour/editor.cc:129 gtk_ardour/editor.cc:4106 +msgid "Beats/32" +msgstr "долÑм/32" + +#: gtk_ardour/editor.cc:130 gtk_ardour/editor.cc:4104 +msgid "Beats/16" +msgstr "долÑм/16" + +#: gtk_ardour/editor.cc:131 gtk_ardour/editor.cc:4102 +msgid "Beats/8" +msgstr "долÑм/8" + +#: gtk_ardour/editor.cc:132 gtk_ardour/editor.cc:4100 +msgid "Beats/4" +msgstr "долÑм/4" + +#: gtk_ardour/editor.cc:133 gtk_ardour/editor.cc:4098 +msgid "Beats/3" +msgstr "долÑм/3" + +#: gtk_ardour/editor.cc:134 gtk_ardour/editor.cc:4108 +msgid "Beats" +msgstr "долÑм" + +#: gtk_ardour/editor.cc:135 gtk_ardour/editor.cc:4110 +msgid "Bars" +msgstr "тактам" + +#: gtk_ardour/editor.cc:136 gtk_ardour/editor.cc:4112 +msgid "Marks" +msgstr "маркерам" + +#: gtk_ardour/editor.cc:137 gtk_ardour/editor.cc:156 gtk_ardour/editor.cc:4114 +#: gtk_ardour/editor.cc:4182 +msgid "Edit Cursor" +msgstr "курÑору" + +#: gtk_ardour/editor.cc:138 gtk_ardour/editor.cc:4116 +msgid "Region starts" +msgstr "нач. облаÑтей" + +#: gtk_ardour/editor.cc:139 gtk_ardour/editor.cc:4118 +msgid "Region ends" +msgstr "оконч. облаÑтей" + +#: gtk_ardour/editor.cc:140 gtk_ardour/editor.cc:4122 +msgid "Region syncs" +msgstr "" + +#: gtk_ardour/editor.cc:141 gtk_ardour/editor.cc:4120 +msgid "Region bounds" +msgstr "" + +#: gtk_ardour/editor.cc:146 gtk_ardour/editor.cc:4153 +#: gtk_ardour/time_axis_view.cc:449 +msgid "Normal" +msgstr "Ðорм." + +#: gtk_ardour/editor.cc:147 gtk_ardour/editor.cc:4155 +msgid "Magnetic" +msgstr "Магн." + +#: gtk_ardour/editor.cc:152 gtk_ardour/editor.cc:4174 +#: gtk_ardour/export_dialog.cc:1232 gtk_ardour/export_dialog.cc:1237 +msgid "Left" +msgstr "лев. краю" + +#: gtk_ardour/editor.cc:153 gtk_ardour/editor.cc:4176 +#: gtk_ardour/export_dialog.cc:1233 gtk_ardour/export_dialog.cc:1238 +msgid "Right" +msgstr "прав. краю" + +#: gtk_ardour/editor.cc:154 gtk_ardour/editor.cc:4178 +msgid "Center" +msgstr "центру" + +#: gtk_ardour/editor.cc:155 gtk_ardour/editor.cc:4180 +msgid "Playhead" +msgstr "указателю" + +#: gtk_ardour/editor.cc:201 +msgid "Mins:Secs" +msgstr "Мин:Сек" + +#: gtk_ardour/editor.cc:204 gtk_ardour/editor_rulers.cc:353 +msgid "Frames" +msgstr "Кадр" + +#: gtk_ardour/editor.cc:205 gtk_ardour/editor_rulers.cc:373 +msgid "Tempo" +msgstr "Темп" + +#: gtk_ardour/editor.cc:206 gtk_ardour/editor_rulers.cc:367 +msgid "Meter" +msgstr "Размер" + +#: gtk_ardour/editor.cc:207 gtk_ardour/editor_rulers.cc:379 +msgid "Location Markers" +msgstr "Маркеры интервалов" + +#: gtk_ardour/editor.cc:208 gtk_ardour/editor_rulers.cc:385 +msgid "Range Markers" +msgstr "" + +#: gtk_ardour/editor.cc:209 gtk_ardour/editor_rulers.cc:391 +msgid "Loop/Punch Ranges" +msgstr "" + +#: gtk_ardour/editor.cc:221 +msgid "" +"editor\n" +"mixer" +msgstr "" +"редактор\n" +"микшер" + +#: gtk_ardour/editor.cc:232 +msgid "range" +msgstr "выделÑть" + +#: gtk_ardour/editor.cc:233 +msgid "object" +msgstr "объект" + +#: gtk_ardour/editor.cc:235 +msgid "zoom" +msgstr "маÑштаб" + +#: gtk_ardour/editor.cc:236 +msgid "timefx" +msgstr "Ñффект" + +#: gtk_ardour/editor.cc:237 +msgid "listen" +msgstr "" + +#: gtk_ardour/editor.cc:239 +msgid "mode" +msgstr "режим" + +#: gtk_ardour/editor.cc:240 +msgid "automation" +msgstr "автомат" + +#: gtk_ardour/editor.cc:242 +msgid "Edit Mode" +msgstr "Режим редактированиÑ" + +#: gtk_ardour/editor.cc:243 +msgid "Snap To" +msgstr "ПривÑзка к" + +#: gtk_ardour/editor.cc:244 +msgid "Snap Mode" +msgstr "ПривÑзка к" + +#: gtk_ardour/editor.cc:245 +msgid "Zoom Focus" +msgstr "МаÑштабировать к" + +#: gtk_ardour/editor.cc:256 gtk_ardour/editor.cc:2364 +#: gtk_ardour/editor.cc:2524 gtk_ardour/editor.cc:2579 +msgid "Nudge" +msgstr "" + +#: gtk_ardour/editor.cc:511 +msgid "Zoom in" +msgstr "Увеличить" + +#: gtk_ardour/editor.cc:512 +msgid "Zoom out" +msgstr "Уменьшить" + +#: gtk_ardour/editor.cc:517 +msgid "Zoom to session" +msgstr "Показать вÑÑ‘" + +#: gtk_ardour/editor.cc:536 +msgid "Zoom Span" +msgstr "ОблаÑть проÑмотра" + +#: gtk_ardour/editor.cc:566 +msgid "Edit Groups" +msgstr "" +"Ред.\n" +"группы" + +#: gtk_ardour/editor.cc:591 gtk_ardour/mixer_ui.cc:142 +msgid "-all-" +msgstr "-вÑе-" + +#: gtk_ardour/editor.cc:718 +msgid "Nudge region/selection forwards" +msgstr "" + +#: gtk_ardour/editor.cc:719 +msgid "Nudge region/selection backwards" +msgstr "" + +#: gtk_ardour/editor.cc:728 gtk_ardour/editor_mixer.cc:308 +msgid "ardour: editor" +msgstr "ardour: редактор" + +#: gtk_ardour/editor.cc:729 +msgid "ardour_editor" +msgstr "ardour_редактор" + +#: gtk_ardour/editor.cc:846 +msgid "VerboseCanvasCursor" +msgstr "" + +#: gtk_ardour/editor.cc:1405 +msgid "FirstActionMessage" +msgstr "" + +#: gtk_ardour/editor.cc:1407 +msgid "Start a new session\n" +msgstr "Ðачать новую ÑеÑÑию\n" + +#: gtk_ardour/editor.cc:1408 +msgid "via Session menu" +msgstr "в меню \"СеÑÑиÑ\"" + +#: gtk_ardour/editor.cc:1703 +msgid "ardour: editor: " +msgstr "ardour: редактор: " + +#: gtk_ardour/editor.cc:1787 gtk_ardour/editor.cc:1796 +#: gtk_ardour/editor_markers.cc:797 +msgid "Loop" +msgstr "Кольцо" + +#: gtk_ardour/editor.cc:1801 gtk_ardour/editor.cc:1810 +#: gtk_ardour/editor_markers.cc:823 +msgid "Punch" +msgstr "Врезка" + +#: gtk_ardour/editor.cc:1957 gtk_ardour/editor_mouse.cc:1688 +#, fuzzy +msgid "programming error: fade in canvas item has no regionview data pointer!" +msgstr "ошибка в программе: line canvas item has no line pointer!" + +#: gtk_ardour/editor.cc:1969 gtk_ardour/editor.cc:1986 +#: gtk_ardour/redirect_box.cc:401 +msgid "Deactivate" +msgstr "Деактивировать" + +#: gtk_ardour/editor.cc:1971 gtk_ardour/editor.cc:1988 +#: gtk_ardour/redirect_box.cc:398 +msgid "Activate" +msgstr "Ðктивировать" + +#: gtk_ardour/editor.cc:1976 gtk_ardour/editor.cc:1993 +#, fuzzy +msgid "Linear" +msgstr "линейное" + +#: gtk_ardour/editor.cc:1977 gtk_ardour/editor.cc:1994 +#: gtk_ardour/option_editor.cc:358 gtk_ardour/option_editor.cc:734 +#: gtk_ardour/option_editor.cc:796 +#, fuzzy +msgid "Slowest" +msgstr "Меньше" + +#: gtk_ardour/editor.cc:1978 gtk_ardour/editor.cc:1995 +#: gtk_ardour/option_editor.cc:360 gtk_ardour/option_editor.cc:735 +#: gtk_ardour/option_editor.cc:798 +#, fuzzy +msgid "Slow" +msgstr "Соло" + +#: gtk_ardour/editor.cc:1979 gtk_ardour/editor.cc:1996 +#: gtk_ardour/option_editor.cc:364 gtk_ardour/option_editor.cc:737 +#: gtk_ardour/option_editor.cc:802 +#, fuzzy +msgid "Fast" +msgstr "Затухание" + +#: gtk_ardour/editor.cc:1980 gtk_ardour/editor.cc:1997 +#: gtk_ardour/option_editor.cc:368 gtk_ardour/option_editor.cc:739 +#: gtk_ardour/option_editor.cc:806 +#, fuzzy +msgid "Fastest" +msgstr "быÑтрое" + +#: gtk_ardour/editor.cc:2105 gtk_ardour/editor.cc:2113 +msgid "Freeze" +msgstr "Заморозить" + +#: gtk_ardour/editor.cc:2109 +msgid "Unfreeze" +msgstr "Разморозить" + +#: gtk_ardour/editor.cc:2238 gtk_ardour/editor.cc:2328 +#, fuzzy +msgid "Unmute" +msgstr "тихо" + +#: gtk_ardour/editor.cc:2247 +msgid "Convert to short" +msgstr "" + +#: gtk_ardour/editor.cc:2249 +msgid "Convert to full" +msgstr "" + +#: gtk_ardour/editor.cc:2260 +#, fuzzy +msgid "Crossfade" +msgstr "КроÑÑфейд" + +#: gtk_ardour/editor.cc:2303 +msgid "Popup region editor" +msgstr "Открыть редактор облаÑти" + +#: gtk_ardour/editor.cc:2304 +#, fuzzy +msgid "Raise to top layer" +msgstr "ПоднÑть облаÑть в верхний Ñлой" + +#: gtk_ardour/editor.cc:2305 +#, fuzzy +msgid "Lower to bottom layer" +msgstr "ОпуÑтить облаÑть в нижний Ñлой" + +#: gtk_ardour/editor.cc:2307 +msgid "Define sync point" +msgstr "" + +#: gtk_ardour/editor.cc:2308 +msgid "Remove sync point" +msgstr "" + +#: gtk_ardour/editor.cc:2313 +#, fuzzy +msgid "Bounce" +msgstr "СвеÑти выделенное" + +#: gtk_ardour/editor.cc:2323 +msgid "Lock" +msgstr "" + +#: gtk_ardour/editor.cc:2324 +msgid "Unlock" +msgstr "" + +#: gtk_ardour/editor.cc:2334 +msgid "Original position" +msgstr "" + +#: gtk_ardour/editor.cc:2340 +msgid "Toggle envelope visibility" +msgstr "" + +#: gtk_ardour/editor.cc:2341 +msgid "Toggle envelope active" +msgstr "" + +#: gtk_ardour/editor.cc:2345 +#, fuzzy +msgid "DeNormalize" +msgstr "Ðорм." + +#: gtk_ardour/editor.cc:2347 +msgid "Normalize" +msgstr "" + +#: gtk_ardour/editor.cc:2350 +msgid "Reverse" +msgstr "" + +#: gtk_ardour/editor.cc:2359 +msgid "Nudge fwd" +msgstr "" + +#: gtk_ardour/editor.cc:2360 +msgid "Nudge bwd" +msgstr "" + +#: gtk_ardour/editor.cc:2361 +msgid "Nudge fwd by capture offset" +msgstr "" + +#: gtk_ardour/editor.cc:2362 +msgid "Nudge bwd by capture offset" +msgstr "" + +#: gtk_ardour/editor.cc:2371 +msgid "Start to edit cursor" +msgstr "От начала до курÑора" + +#: gtk_ardour/editor.cc:2372 +msgid "Edit cursor to end" +msgstr "От курÑора до конца" + +#: gtk_ardour/editor.cc:2374 +msgid "Trim" +msgstr "" + +#: gtk_ardour/editor.cc:2377 +msgid "Split" +msgstr "Склеить" + +#: gtk_ardour/editor.cc:2380 +msgid "Make mono regions" +msgstr "Создать моно-облаÑти" + +#: gtk_ardour/editor.cc:2383 gtk_ardour/editor.cc:2428 +msgid "Duplicate" +msgstr "Размножить" + +#: gtk_ardour/editor.cc:2384 +msgid "Fill Track" +msgstr "Заполнить трек" + +#: gtk_ardour/editor.cc:2388 +msgid "Destroy" +msgstr "" + +#: gtk_ardour/editor.cc:2418 +#, fuzzy +msgid "Play range" +msgstr "ВоÑпроизвеÑти \"кольцо\"" + +#: gtk_ardour/editor.cc:2419 gtk_ardour/editor_markers.cc:446 +msgid "Loop range" +msgstr "" + +#: gtk_ardour/editor.cc:2421 +#, fuzzy +msgid "Create chunk from range" +msgstr "Создать фрагмент из выделенного" + +#: gtk_ardour/editor.cc:2423 +msgid "Create Region" +msgstr "Создать облаÑть" + +#: gtk_ardour/editor.cc:2424 +msgid "Separate Region" +msgstr "Разделить облаÑть" + +#: gtk_ardour/editor.cc:2425 +#, fuzzy +msgid "Crop Region to range" +msgstr "Обрезать облаÑть по выделенному" + +#: gtk_ardour/editor.cc:2426 +msgid "Bounce range" +msgstr "" + +#: gtk_ardour/editor.cc:2432 +#, fuzzy +msgid "Fill range w/Region" +msgstr "Создать облаÑть" + +#: gtk_ardour/editor.cc:2434 +#, fuzzy +msgid "Range" +msgstr "выделÑть" + +#: gtk_ardour/editor.cc:2449 gtk_ardour/editor.cc:2538 +#, fuzzy +msgid "Play from edit cursor" +msgstr "ВоÑпроизвеÑти от курÑора" + +#: gtk_ardour/editor.cc:2450 gtk_ardour/editor.cc:2539 +msgid "Play from start" +msgstr "ВоÑпроизвеÑти Ñ Ð½Ð°Ñ‡Ð°Ð»Ð°" + +#: gtk_ardour/editor.cc:2451 +#, fuzzy +msgid "Play region" +msgstr "ВоÑпроизвеÑти облаÑть" + +#: gtk_ardour/editor.cc:2453 +msgid "Loop Region" +msgstr "\"Закольцевать\" облаÑть" + +#: gtk_ardour/editor.cc:2455 gtk_ardour/editor.cc:2540 +#: gtk_ardour/library_ui.cc:972 +msgid "Play" +msgstr "ВоÑпроизвеÑти" + +#: gtk_ardour/editor.cc:2463 gtk_ardour/editor.cc:2548 +#, fuzzy +msgid "Select All in track" +msgstr "Выделить вÑÑ‘" + +#: gtk_ardour/editor.cc:2464 gtk_ardour/editor.cc:2549 +#, fuzzy +msgid "Select All" +msgstr "Выделить вÑÑ‘" + +#: gtk_ardour/editor.cc:2465 gtk_ardour/editor.cc:2550 +#, fuzzy +msgid "Invert in track" +msgstr "Скрыть трек" + +#: gtk_ardour/editor.cc:2466 gtk_ardour/editor.cc:2551 +#, fuzzy +msgid "Invert" +msgstr "Ðовый \"возврат\"" + +#: gtk_ardour/editor.cc:2468 gtk_ardour/editor.cc:2553 +#, fuzzy +msgid "Select loop range" +msgstr "выбрать окно проÑмотра" + +#: gtk_ardour/editor.cc:2469 gtk_ardour/editor.cc:2554 +#, fuzzy +msgid "Select punch range" +msgstr "Выбрать текущий интервал" + +#: gtk_ardour/editor.cc:2480 gtk_ardour/editor.cc:2565 +#: gtk_ardour/editor.cc:3916 gtk_ardour/redirect_box.cc:369 +msgid "Cut" +msgstr "Вырезать" + +#: gtk_ardour/editor.cc:2481 gtk_ardour/editor.cc:2566 +#: gtk_ardour/editor.cc:3918 gtk_ardour/redirect_box.cc:371 +msgid "Copy" +msgstr "Копировать" + +#: gtk_ardour/editor.cc:2482 +#, fuzzy +msgid "Paste at edit cursor" +msgstr "От начала до курÑора" + +#: gtk_ardour/editor.cc:2483 +#, fuzzy +msgid "Paste at mouse" +msgstr "иÑпользовать маÑтер-выходы" + +#: gtk_ardour/editor.cc:2487 gtk_ardour/editor.cc:3923 +msgid "Align" +msgstr "ВыровнÑть" + +#: gtk_ardour/editor.cc:2488 gtk_ardour/editor.cc:3925 +msgid "Align Relative" +msgstr "ВыровнÑть отноÑительно" + +#: gtk_ardour/editor.cc:2492 +msgid "Insert chunk" +msgstr "Ð’Ñтавить фрагмент" + +#: gtk_ardour/editor.cc:2496 +#, fuzzy +msgid "New Region from range" +msgstr "Создать облаÑть из выделенного" + +#: gtk_ardour/editor.cc:2497 +#, fuzzy +msgid "Separate Range" +msgstr "Разделить облаÑть" + +#: gtk_ardour/editor.cc:2507 +msgid "Insert Region" +msgstr "Ð’Ñтавить облаÑть" + +#: gtk_ardour/editor.cc:2508 +msgid "Insert external sndfile" +msgstr "Ð’Ñтавить внешний аудиофайл" + +#: gtk_ardour/editor.cc:2510 gtk_ardour/library_ui.cc:1438 +msgid "Import" +msgstr "Импорт" + +#: gtk_ardour/editor.cc:2519 gtk_ardour/editor.cc:2574 +msgid "Nudge entire track fwd" +msgstr "" + +#: gtk_ardour/editor.cc:2520 gtk_ardour/editor.cc:2575 +msgid "Nudge track after edit cursor fwd" +msgstr "" + +#: gtk_ardour/editor.cc:2521 gtk_ardour/editor.cc:2576 +msgid "Nudge entire track bwd" +msgstr "" + +#: gtk_ardour/editor.cc:2522 gtk_ardour/editor.cc:2577 +msgid "Nudge track after edit cursor bwd" +msgstr "" + +#: gtk_ardour/editor.cc:2567 gtk_ardour/editor.cc:3920 +#: gtk_ardour/redirect_box.cc:373 +msgid "Paste" +msgstr "Ð’Ñтавить" + +#: gtk_ardour/editor.cc:2632 gtk_ardour/editor.cc:2645 +#: gtk_ardour/editor_markers.cc:287 gtk_ardour/location_ui.cc:799 +msgid "add marker" +msgstr "добавить маркер" + +#: gtk_ardour/editor.cc:3084 +msgid "select/move objects" +msgstr "выбирать/двигать объекты" + +#: gtk_ardour/editor.cc:3085 +msgid "select/move ranges" +msgstr "выбирать/двигать диапазоны" + +#: gtk_ardour/editor.cc:3086 +msgid "draw gain automation" +msgstr "" + +#: gtk_ardour/editor.cc:3087 +msgid "select zoom range" +msgstr "выбрать окно проÑмотра" + +#: gtk_ardour/editor.cc:3088 +msgid "stretch/shrink regions" +msgstr "раÑÑ‚Ñнуть/Ñжать облаÑти" + +#: gtk_ardour/editor.cc:3089 +#, fuzzy +msgid "listen to specific regions" +msgstr "ВоÑпроизвеÑти выделенную облаÑть" + +#: gtk_ardour/editor.cc:3213 +msgid "Start:" +msgstr "Ðачало:" + +#: gtk_ardour/editor.cc:3214 +msgid "End:" +msgstr "Конец:" + +#: gtk_ardour/editor.cc:3215 +msgid "Edit:" +msgstr "Редактировать:" + +#: gtk_ardour/editor.cc:3429 +msgid "incorrectly formatted URI list, ignored" +msgstr "" + +#: gtk_ardour/editor.cc:3611 +#, fuzzy +msgid "set selected trackview" +msgstr "Ð’Ñтавить выбранное" + +#: gtk_ardour/editor.cc:3647 +#, fuzzy +msgid "set selected control point" +msgstr "иÑпользовать контрольные выходы" + +#: gtk_ardour/editor.cc:3719 +#, fuzzy +msgid "set selected regionview" +msgstr "ВоÑпроизвеÑти выделенную облаÑть" + +#: gtk_ardour/editor.cc:3799 gtk_ardour/editor.cc:3835 +#, fuzzy +msgid "set selected regions" +msgstr "ВоÑпроизвеÑти выделенную облаÑть" + +#: gtk_ardour/editor.cc:3891 +msgid "Undo" +msgstr "Отменить" + +#: gtk_ardour/editor.cc:3893 +msgid "Undo (%1)" +msgstr "Отменить (%1)" + +#: gtk_ardour/editor.cc:3903 +msgid "Redo" +msgstr "Вернуть" + +#: gtk_ardour/editor.cc:3905 +msgid "Redo (%1)" +msgstr "Вернуть (%1)" + +#: gtk_ardour/editor.cc:3939 gtk_ardour/editor.cc:3946 +msgid "... as new track" +msgstr "" + +#: gtk_ardour/editor.cc:3940 gtk_ardour/editor.cc:3947 +#, fuzzy +msgid "... as new region" +msgstr "проÑлушать облаÑть" + +#: gtk_ardour/editor.cc:3949 gtk_ardour/editor_region_list.cc:452 +msgid "Import audio (copy)" +msgstr "Импортировать аудио (копировать)" + +#: gtk_ardour/editor.cc:3950 gtk_ardour/editor_region_list.cc:457 +msgid "Embed audio (link)" +msgstr "" + +#: gtk_ardour/editor.cc:3953 +msgid "Remove last capture" +msgstr "Удалить поÑледнюю запиÑÑŒ" + +#: gtk_ardour/editor.cc:3974 +msgid "Duplicate how many times?" +msgstr "КоличеÑтво повторов?" + +#: gtk_ardour/editor.cc:4550 +msgid "" +"Playlist %1 is currently unused.\n" +"If left alone, no audio files used by it will be cleaned.\n" +"If deleted, audio files used by it alone by will cleaned." +msgstr "" + +#: gtk_ardour/editor.cc:4555 +#, fuzzy +msgid "Delete playlist" +msgstr "Ð˜Ð¼Ñ Ñнимка" + +#: gtk_ardour/editor.cc:4556 +#, fuzzy +msgid "Keep playlist" +msgstr "Ð˜Ð¼Ñ Ñнимка" + +#: gtk_ardour/editor.cc:4557 +#, fuzzy +msgid "Cancel cleanup" +msgstr "ОчиÑтка" + +#: gtk_ardour/editor_canvas_events.cc:691 gtk_ardour/editor_mouse.cc:2258 +#: gtk_ardour/editor_mouse.cc:2277 gtk_ardour/editor_mouse.cc:2290 +msgid "" +"programming error: control point canvas item has no control point object " +"pointer!" +msgstr "" +"ошибка в программе: control point canvas item has no control point object " +"pointer!" + +#: gtk_ardour/editor_canvas_events.cc:717 +msgid "programming error: line canvas item has no line object pointer!" +msgstr "ошибка в программе: line canvas item has no line object pointer!" + +#: gtk_ardour/editor_canvas_events.cc:744 +#: gtk_ardour/editor_canvas_events.cc:784 +#: gtk_ardour/editor_canvas_events.cc:823 +msgid "programming error: no \"rect\" pointer associated with selection item" +msgstr "ошибка в программе: no \"rect\" pointer associated with selection item" + +#: gtk_ardour/editor_edit_groups.cc:62 gtk_ardour/editor_route_list.cc:298 +#: gtk_ardour/mixer_ui.cc:670 +msgid "Show All" +msgstr "Показать вÑÑ‘" + +#: gtk_ardour/editor_edit_groups.cc:63 gtk_ardour/editor_route_list.cc:299 +#: gtk_ardour/mixer_ui.cc:671 +msgid "Hide All" +msgstr "Скрыть вÑÑ‘" + +#: gtk_ardour/editor_edit_groups.cc:98 +msgid "Name for new edit group" +msgstr "Ð˜Ð¼Ñ Ð½Ð¾Ð²Ð¾Ð¹ группы" + +#: gtk_ardour/editor_export_audio.cc:60 +msgid "" +"There is no range to export.\n" +"\n" +"Select a range using the range mouse mode" +msgstr "" + +#: gtk_ardour/editor_imageframe.cc:675 gtk_ardour/editor_imageframe.cc:707 +msgid "programming error: no ImageFrameView selected" +msgstr "ошибка в программе: no ImageFrameView selected" + +#: gtk_ardour/editor_imageframe.cc:906 gtk_ardour/editor_imageframe.cc:930 +msgid "programming error: no MarkerView selected" +msgstr "ошибка в программе: no MarkerView selected" + +#: gtk_ardour/editor_keys.cc:187 +#, fuzzy +msgid "keyboard selection" +msgstr "Выделить по интервалу" + +#: gtk_ardour/editor_markers.cc:302 gtk_ardour/editor_markers.cc:376 +#: gtk_ardour/editor_markers.cc:508 gtk_ardour/editor_markers.cc:526 +#: gtk_ardour/editor_markers.cc:556 gtk_ardour/editor_markers.cc:584 +#: gtk_ardour/editor_markers.cc:612 gtk_ardour/editor_markers.cc:650 +#: gtk_ardour/editor_markers.cc:677 gtk_ardour/editor_markers.cc:700 +#: gtk_ardour/editor_markers.cc:719 gtk_ardour/editor_mouse.cc:1960 +#: gtk_ardour/editor_mouse.cc:4075 +msgid "programming error: marker canvas item has no marker object pointer!" +msgstr "ошибка в программе: marker canvas item has no marker object pointer!" + +#: gtk_ardour/editor_markers.cc:326 gtk_ardour/location_ui.cc:681 +msgid "remove marker" +msgstr "" + +#: gtk_ardour/editor_markers.cc:444 gtk_ardour/editor_markers.cc:494 +msgid "Locate to" +msgstr "" + +#: gtk_ardour/editor_markers.cc:445 gtk_ardour/editor_markers.cc:495 +msgid "Play from" +msgstr "ВоÑпроизвеÑти от" + +#: gtk_ardour/editor_markers.cc:447 gtk_ardour/editor_markers.cc:496 +#, fuzzy +msgid "Set from playhead" +msgstr "ВоÑпроизвеÑти от указателÑ" + +#: gtk_ardour/editor_markers.cc:448 gtk_ardour/editor_markers.cc:497 +#, fuzzy +msgid "Set from range" +msgstr "выбрать окно проÑмотра" + +#: gtk_ardour/editor_markers.cc:479 +msgid "Set Loop Range" +msgstr "" + +#: gtk_ardour/editor_markers.cc:480 +msgid "Set Punch Range" +msgstr "" + +#: gtk_ardour/editor_markers.cc:736 +msgid "ardour: rename mark" +msgstr "ardour: переименовать маркер" + +#: gtk_ardour/editor_markers.cc:738 +#, fuzzy +msgid "ardour: rename range" +msgstr "ardour: переименовать облаÑть" + +#: gtk_ardour/editor_markers.cc:792 +#, fuzzy +msgid "set loop range" +msgstr "выбрать окно проÑмотра" + +#: gtk_ardour/editor_markers.cc:818 +#, fuzzy +msgid "set punch range" +msgstr "Выбрать текущий интервал" + +#: gtk_ardour/editor_mouse.cc:99 +msgid "Editor::event_frame() used on unhandled event type %1" +msgstr "Editor::event_frame() used on unhandled event type %1" + +#: gtk_ardour/editor_mouse.cc:1555 +msgid "programming error: start_grab called without drag item" +msgstr "ошибка в программе: start_grab called without drag item" + +#: gtk_ardour/editor_mouse.cc:1760 +#, fuzzy +msgid "change fade in length" +msgstr "редактировать введение в уровень" + +#: gtk_ardour/editor_mouse.cc:1778 +#, fuzzy +msgid "programming error: fade out canvas item has no regionview data pointer!" +msgstr "ошибка в программе: cursor canvas item has no cursor data pointer!" + +#: gtk_ardour/editor_mouse.cc:1852 +#, fuzzy +msgid "change fade out length" +msgstr "редактировать Ñведение в ноль" + +#: gtk_ardour/editor_mouse.cc:1871 +msgid "programming error: cursor canvas item has no cursor data pointer!" +msgstr "ошибка в программе: cursor canvas item has no cursor data pointer!" + +#: gtk_ardour/editor_mouse.cc:2098 gtk_ardour/editor_tempodisplay.cc:470 +msgid "" +"programming error: meter marker canvas item has no marker object pointer!" +msgstr "" +"ошибка в программе: meter marker canvas item has no marker object pointer!" + +#: gtk_ardour/editor_mouse.cc:2163 +msgid "move meter mark" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2177 gtk_ardour/editor_tempodisplay.cc:335 +#: gtk_ardour/editor_tempodisplay.cc:420 gtk_ardour/editor_tempodisplay.cc:439 +msgid "" +"programming error: tempo marker canvas item has no marker object pointer!" +msgstr "" +"ошибка в программе: tempo marker canvas item has no marker object pointer!" + +#: gtk_ardour/editor_mouse.cc:2182 gtk_ardour/editor_tempodisplay.cc:340 +#: gtk_ardour/editor_tempodisplay.cc:425 +msgid "programming error: marker for tempo is not a tempo marker!" +msgstr "ошибка в программе: marker for tempo is not a tempo marker!" + +#: gtk_ardour/editor_mouse.cc:2245 +msgid "move tempo mark" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2388 +msgid "programming error: line canvas item has no line pointer!" +msgstr "ошибка в программе: line canvas item has no line pointer!" + +#: gtk_ardour/editor_mouse.cc:2497 +#, fuzzy +msgid "move region(s)" +msgstr "Создать облаÑть" + +#: gtk_ardour/editor_mouse.cc:2509 +msgid "Drag region copy" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:2579 +#, fuzzy +msgid "copy region(s)" +msgstr "ВоÑпроизвеÑти выделенную облаÑть" + +#: gtk_ardour/editor_mouse.cc:2612 +#, fuzzy +msgid "Drag region brush" +msgstr "проÑлушать облаÑть" + +#: gtk_ardour/editor_mouse.cc:3425 +#, fuzzy +msgid "selection grab" +msgstr "Выделенное" + +#: gtk_ardour/editor_mouse.cc:3571 +#, fuzzy +msgid "range selection" +msgstr "ВоÑпроизвеÑти выделенное" + +#: gtk_ardour/editor_mouse.cc:3587 +#, fuzzy +msgid "trim selection start" +msgstr "Выделить по интервалу" + +#: gtk_ardour/editor_mouse.cc:3603 +#, fuzzy +msgid "trim selection end" +msgstr "Выделить по интервалу" + +#: gtk_ardour/editor_mouse.cc:3620 +#, fuzzy +msgid "move selection" +msgstr "СвеÑти выделенное" + +#: gtk_ardour/editor_mouse.cc:3995 +#, fuzzy +msgid "Start point trim" +msgstr "От начала до курÑора" + +#: gtk_ardour/editor_mouse.cc:4023 +msgid "End point trim" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:4062 +msgid "trimmed region" +msgstr "" + +#: gtk_ardour/editor_mouse.cc:4203 +#, fuzzy +msgid "new range marker" +msgstr "Маркеры интервалов" + +#: gtk_ardour/editor_mouse.cc:4422 +#, fuzzy +msgid "select regions" +msgstr "ВоÑпроизвеÑти выделенную облаÑть" + +#: gtk_ardour/editor_mouse.cc:4451 +msgid "Name for region:" +msgstr "Ð˜Ð¼Ñ Ð¾Ð±Ð»Ð°Ñти: " + +#: gtk_ardour/editor_mouse.cc:4517 +#, fuzzy +msgid "timestretch" +msgstr "ardour: Ñффект timestretch" + +#: gtk_ardour/editor_ops.cc:117 +#, fuzzy +msgid "split" +msgstr "Склеить" + +#: gtk_ardour/editor_ops.cc:153 +#, fuzzy +msgid "remove region" +msgstr "Создать облаÑть" + +#: gtk_ardour/editor_ops.cc:172 +msgid "" +" This is destructive, will possibly delete audio files\n" +"It cannot be undone\n" +"Do you really want to destroy %1 ?" +msgstr "" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "these regions" +msgstr "ВоÑпроизвеÑти выделенную облаÑть" + +#: gtk_ardour/editor_ops.cc:176 +#, fuzzy +msgid "this region" +msgstr "отключить воÑпроизведение Ñтой облаÑти" + +#: gtk_ardour/editor_ops.cc:179 +#, fuzzy +msgid "Yes, destroy them." +msgstr "Да" + +#: gtk_ardour/editor_ops.cc:181 gtk_ardour/editor_ops.cc:3434 +msgid "Yes, destroy it." +msgstr "Да" + +#: gtk_ardour/editor_ops.cc:184 gtk_ardour/editor_ops.cc:3435 +#: gtk_ardour/route_ui.cc:658 gtk_ardour/visual_time_axis.cc:300 +msgid "No, do nothing." +msgstr "Ðет" + +#: gtk_ardour/editor_ops.cc:279 gtk_ardour/editor_ops.cc:307 +#, fuzzy +msgid "extend selection" +msgstr "Выделить по интервалу" + +#: gtk_ardour/editor_ops.cc:323 gtk_ardour/editor_ops.cc:357 +#: gtk_ardour/editor_ops.cc:401 gtk_ardour/editor_ops.cc:427 +msgid "nudge forward" +msgstr "" + +#: gtk_ardour/editor_ops.cc:491 +msgid "build_region_boundary_cache called with snap_type = %1" +msgstr "build_region_boundary_cache called with snap_type = %1" + +#: gtk_ardour/editor_ops.cc:1305 +#, fuzzy +msgid "set selection from range" +msgstr "Создать облаÑть из выделенного" + +#: gtk_ardour/editor_ops.cc:1421 +msgid "clear markers" +msgstr "очиÑтить маркеры" + +#: gtk_ardour/editor_ops.cc:1433 +msgid "clear ranges" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1452 +msgid "clear locations" +msgstr "очиÑтить интервалы" + +#: gtk_ardour/editor_ops.cc:1503 +#, fuzzy +msgid "insert dragged region" +msgstr "Ð’Ñтавить облаÑть" + +#: gtk_ardour/editor_ops.cc:1538 +#, fuzzy +msgid "insert region" +msgstr "Ð’Ñтавить облаÑть" + +#: gtk_ardour/editor_ops.cc:1744 +msgid "ardour: rename region" +msgstr "ardour: переименовать облаÑть" + +#: gtk_ardour/editor_ops.cc:1891 +msgid "You can't import an audiofile until you have a session loaded." +msgstr "Ð’Ñ‹ не можете импортировать аудиофайл пока ÑеÑÑÐ¸Ñ Ð½Ðµ загружена." + +#: gtk_ardour/editor_ops.cc:1901 +#, fuzzy +msgid "Import selected as tracks" +msgstr "" +"Импортировать\n" +"выбранное" + +#: gtk_ardour/editor_ops.cc:1904 +#, fuzzy +msgid "Import selected to region list" +msgstr "ВоÑпроизвеÑти выделенную облаÑть" + +#: gtk_ardour/editor_ops.cc:1933 +msgid "ardour: audio import in progress" +msgstr "ardour: ... идёт импорт аудио" + +#: gtk_ardour/editor_ops.cc:1937 +msgid "Cancel Import" +msgstr "Отменить импорт" + +#: gtk_ardour/editor_ops.cc:1944 +#, fuzzy +msgid "ardour: importing %1" +msgstr "ardour: ÑкÑпорт" + +#: gtk_ardour/editor_ops.cc:1990 +msgid "%1 it anyway" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1996 +#, fuzzy +msgid "Don't %1 it" +msgstr "Отмена" + +#: gtk_ardour/editor_ops.cc:1997 +msgid "%1 all without questions" +msgstr "" + +#: gtk_ardour/editor_ops.cc:1998 +#, fuzzy +msgid "Cancel entire import" +msgstr "Отменить импорт" + +#: gtk_ardour/editor_ops.cc:2004 +#, fuzzy +msgid "" +"%1\n" +"This audiofile's sample rate doesn't match the session sample rate!" +msgstr "" +"Выбранный аудиофайл имеет чаÑтоту диÑкретизации данных\n" +"отличную от текущей ÑеÑÑии!" + +#: gtk_ardour/editor_ops.cc:2032 +msgid "You can't embed an audiofile until you have a session loaded." +msgstr "Ð’Ñ‹ не можете импортировать аудиофайл пока ÑеÑÑÐ¸Ñ Ð½Ðµ загружена." + +#: gtk_ardour/editor_ops.cc:2039 +msgid "Add to External Region list" +msgstr "Добавить во внешний ÑпиÑок облаÑтей" + +#: gtk_ardour/editor_ops.cc:2090 gtk_ardour/editor_ops.cc:2210 +#: gtk_ardour/editor_ops.cc:2286 +msgid "Editor: cannot open file \"%1\" (%2)" +msgstr "Редактор: не удалоÑÑŒ открыть файл \"%1\" (%2)" + +#: gtk_ardour/editor_ops.cc:2128 gtk_ardour/editor_ops.cc:2312 +msgid "could not open %1" +msgstr "не удалоÑÑŒ открыть %1" + +#: gtk_ardour/editor_ops.cc:2171 +#, fuzzy +msgid "Insert selected as new tracks" +msgstr "Ð’Ñтавить выбранное" + +#: gtk_ardour/editor_ops.cc:2186 +msgid "Insert selected" +msgstr "Ð’Ñтавить выбранное" + +#: gtk_ardour/editor_ops.cc:2327 +#, fuzzy +msgid "insert sndfile" +msgstr "Ð’Ñтавить внешний аудиофайл" + +#: gtk_ardour/editor_ops.cc:2464 +#, fuzzy +msgid "separate" +msgstr "Разделить облаÑть" + +#: gtk_ardour/editor_ops.cc:2528 +#, fuzzy +msgid "trim to selection" +msgstr "Выделить по интервалу" + +#: gtk_ardour/editor_ops.cc:2568 +msgid "region fill" +msgstr "" + +#: gtk_ardour/editor_ops.cc:2626 +#, fuzzy +msgid "fill selection" +msgstr "Закольцевать выделенное" + +#: gtk_ardour/editor_ops.cc:2650 +msgid "Place the edit cursor at the desired sync point" +msgstr "ПомеÑтите курÑор на точку Ñинхронизации" + +#: gtk_ardour/editor_ops.cc:2656 +#, fuzzy +msgid "set sync from edit cursor" +msgstr "ВоÑпроизвеÑти от курÑора" + +#: gtk_ardour/editor_ops.cc:2668 +msgid "remove sync" +msgstr "" + +#: gtk_ardour/editor_ops.cc:2682 +msgid "naturalize" +msgstr "" + +#: gtk_ardour/editor_ops.cc:2746 +#, fuzzy +msgid "align selection (relative)" +msgstr "ВыровнÑть отноÑительно" + +#: gtk_ardour/editor_ops.cc:2774 +#, fuzzy +msgid "align selection" +msgstr "СвеÑти выделенное" + +#: gtk_ardour/editor_ops.cc:2786 +#, fuzzy +msgid "align region" +msgstr "проÑлушать облаÑть" + +#: gtk_ardour/editor_ops.cc:2833 gtk_ardour/editor_ops.cc:2858 +#, fuzzy +msgid "trim to edit" +msgstr "От начала до курÑора" + +#: gtk_ardour/editor_ops.cc:2909 +#, fuzzy +msgid "ardour: freeze" +msgstr "ardour: " + +#: gtk_ardour/editor_ops.cc:2914 +#, fuzzy +msgid "Cancel Freeze" +msgstr "Отмена" + +#: gtk_ardour/editor_ops.cc:2951 +#, fuzzy +msgid "bounce range" +msgstr "Выбрать текущий интервал" + +#: gtk_ardour/editor_ops.cc:3004 +msgid "cut" +msgstr "вырезать" + +#: gtk_ardour/editor_ops.cc:3007 +msgid "copy" +msgstr "копировать" + +#: gtk_ardour/editor_ops.cc:3020 +msgid " objects" +msgstr "объекты" + +#: gtk_ardour/editor_ops.cc:3046 +msgid " range" +msgstr "" + +#: gtk_ardour/editor_ops.cc:3201 +#, fuzzy +msgid "paste" +msgstr "Ð’Ñтавить" + +#: gtk_ardour/editor_ops.cc:3236 +#, fuzzy +msgid "paste chunk" +msgstr "Создать фрагмент" + +#: gtk_ardour/editor_ops.cc:3276 +#, fuzzy +msgid "duplicate region" +msgstr "Разделить облаÑть" + +#: gtk_ardour/editor_ops.cc:3309 +#, fuzzy +msgid "duplicate selection" +msgstr "СвеÑти выделенное" + +#: gtk_ardour/editor_ops.cc:3349 +#, fuzzy +msgid "clear playlist" +msgstr "Ð˜Ð¼Ñ Ñнимка" + +#: gtk_ardour/editor_ops.cc:3378 +#, fuzzy +msgid "nudge track" +msgstr "Скрыть трек" + +#: gtk_ardour/editor_ops.cc:3431 +msgid "" +"Do you really want to destroy the last capture?\n" +"(This is destructive and cannot be undone)" +msgstr "" +"ПоÑледнюю запиÑÑŒ будет удалена. Ð’Ñ‹ уверены?\n" +"(отмена операции невозможна)" + +#: gtk_ardour/editor_ops.cc:3463 +#, fuzzy +msgid "normalize" +msgstr "Ðорм." + +#: gtk_ardour/editor_ops.cc:3510 +msgid "reverse regions" +msgstr "" + +#: gtk_ardour/editor_region_list.cc:223 +#, fuzzy +msgid "hidden" +msgstr "Скрытый" + +#: gtk_ardour/editor_region_list.cc:408 +msgid "Show all" +msgstr "Показать вÑÑ‘" + +#: gtk_ardour/editor_region_list.cc:417 +msgid "Ascending" +msgstr "по возраÑтанию" + +#: gtk_ardour/editor_region_list.cc:419 +msgid "Descending" +msgstr "по убыванию" + +#: gtk_ardour/editor_region_list.cc:423 +msgid "By Region Name" +msgstr "по имени облаÑти" + +#: gtk_ardour/editor_region_list.cc:425 +msgid "By Region Length" +msgstr "по длине облаÑти" + +#: gtk_ardour/editor_region_list.cc:427 +msgid "By Region Position" +msgstr "по раÑположению облаÑти" + +#: gtk_ardour/editor_region_list.cc:429 +msgid "By Region Timestamp" +msgstr "по времени ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¾Ð±Ð»Ð°Ñти" + +#: gtk_ardour/editor_region_list.cc:431 +msgid "By Region Start in File" +msgstr "по началу облаÑти в файле" + +#: gtk_ardour/editor_region_list.cc:433 +msgid "By Region End in File" +msgstr "по концу облаÑти в файле" + +#: gtk_ardour/editor_region_list.cc:435 +msgid "By Source File Name" +msgstr "по имени файла" + +#: gtk_ardour/editor_region_list.cc:437 +msgid "By Source File Length" +msgstr "по размеру файла" + +#: gtk_ardour/editor_region_list.cc:439 +msgid "By Source File Creation Date" +msgstr "по дате ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ð¸Ñходного файла" + +#: gtk_ardour/editor_region_list.cc:441 +msgid "By Source Filesystem" +msgstr "по раÑположению файла" + +#: gtk_ardour/editor_region_list.cc:444 +msgid "Sorting" +msgstr "Сортировка" + +#: gtk_ardour/editor_region_list.cc:808 +msgid "Regions/length" +msgstr "ОблаÑти/длина" + +#: gtk_ardour/editor_region_list.cc:812 +msgid "Regions/position" +msgstr "ОблаÑти/положение" + +#: gtk_ardour/editor_region_list.cc:816 +msgid "Regions/creation" +msgstr "ОблаÑти/Ñоздание" + +#: gtk_ardour/editor_region_list.cc:820 +msgid "Regions/start" +msgstr "ОблаÑти/начало" + +#: gtk_ardour/editor_region_list.cc:824 +msgid "Regions/end" +msgstr "ОблаÑти/конец" + +#: gtk_ardour/editor_region_list.cc:828 +msgid "Regions/file name" +msgstr "ОблаÑти/Ð¸Ð¼Ñ Ñ„Ð°Ð¹Ð»Ð°" + +#: gtk_ardour/editor_region_list.cc:832 +msgid "Regions/file size" +msgstr "ОблаÑти/размер файла" + +#: gtk_ardour/editor_region_list.cc:836 +msgid "Regions/file date" +msgstr "ОблаÑти/дата файла" + +#: gtk_ardour/editor_region_list.cc:840 +msgid "Regions/file system" +msgstr "ОблаÑти/Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð°Ñ ÑиÑтема" + +#: gtk_ardour/editor_route_list.cc:72 gtk_ardour/editor_route_list.cc:73 +#: gtk_ardour/editor_route_list.cc:231 +msgid "editor" +msgstr "редактор" + +#: gtk_ardour/editor_route_list.cc:300 +msgid "Show All AbstractTracks" +msgstr "Показать вÑе треки" + +#: gtk_ardour/editor_route_list.cc:301 +msgid "Hide All AbstractTracks" +msgstr "Скрыть вÑе треки" + +#: gtk_ardour/editor_route_list.cc:302 +msgid "Show All AudioBus" +msgstr "Показать вÑе аудиошины" + +#: gtk_ardour/editor_route_list.cc:303 +msgid "Hide All AudioBus" +msgstr "Скрыть вÑе аудиошины" + +#: gtk_ardour/editor_rulers.cc:311 +#, fuzzy +msgid "New location marker" +msgstr "Маркеры интервалов" + +#: gtk_ardour/editor_rulers.cc:312 +#, fuzzy +msgid "Clear all locations" +msgstr "очиÑтить интервалы" + +#: gtk_ardour/editor_rulers.cc:317 +#, fuzzy +msgid "Clear all ranges" +msgstr "ВоÑпроизвеÑти \"кольцо\"" + +#: gtk_ardour/editor_rulers.cc:326 +#, fuzzy +msgid "New Tempo" +msgstr "Ðовый темп" + +#: gtk_ardour/editor_rulers.cc:327 +#, fuzzy +msgid "Clear tempo" +msgstr "Ðовый темп" + +#: gtk_ardour/editor_rulers.cc:332 +#, fuzzy +msgid "New Meter" +msgstr "Размер" + +#: gtk_ardour/editor_rulers.cc:333 +#, fuzzy +msgid "Clear meter" +msgstr "очиÑтить маркеры" + +#: gtk_ardour/editor_rulers.cc:341 +#, fuzzy +msgid "Min:Secs" +msgstr "Мин:Сек" + +#: gtk_ardour/editor_selection_list.cc:117 +msgid "name for chunk:" +msgstr "Ð¸Ð¼Ñ Ñ„Ñ€Ð°Ð³Ð¼ÐµÐ½Ñ‚Ð°:" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Create chunk" +msgstr "Создать фрагмент" + +#: gtk_ardour/editor_selection_list.cc:119 +msgid "Forget it" +msgstr "Забыть" + +#: gtk_ardour/editor_tempodisplay.cc:252 gtk_ardour/editor_tempodisplay.cc:295 +msgid "add" +msgstr "добавить" + +#: gtk_ardour/editor_tempodisplay.cc:276 +#, fuzzy +msgid "add tempo mark" +msgstr "добавить маркер" + +#: gtk_ardour/editor_tempodisplay.cc:318 +#, fuzzy +msgid "add meter mark" +msgstr "добавить маркер" + +#: gtk_ardour/editor_tempodisplay.cc:352 gtk_ardour/editor_tempodisplay.cc:383 +msgid "done" +msgstr "готово" + +#: gtk_ardour/editor_tempodisplay.cc:372 gtk_ardour/editor_tempodisplay.cc:404 +msgid "replace tempo mark" +msgstr "" + +#: gtk_ardour/editor_tempodisplay.cc:444 gtk_ardour/editor_tempodisplay.cc:475 +msgid "programming error: marker for meter is not a meter marker!" +msgstr "ошибка в программе: marker for meter is not a meter marker!" + +#: gtk_ardour/editor_tempodisplay.cc:454 gtk_ardour/editor_tempodisplay.cc:487 +#, fuzzy +msgid "remove tempo mark" +msgstr "Да, удалить вÑÑ‘" + +#: gtk_ardour/editor_timefx.cc:50 +msgid "Quick but Ugly" +msgstr "БыÑтро и грубо" + +#: gtk_ardour/editor_timefx.cc:51 +msgid "Skip Anti-aliasing" +msgstr "Без фильтрации" + +#: gtk_ardour/editor_timefx.cc:53 +msgid "Stretch/Shrink it" +msgstr "РаÑÑ‚Ñнуть/Сжать" + +#: gtk_ardour/editor_timefx.cc:57 +msgid "ardour: timestretch" +msgstr "ardour: Ñффект timestretch" + +#: gtk_ardour/editor_timefx.cc:58 +msgid "TimeStretchDialog" +msgstr "TimeStretchDialog" + +#: gtk_ardour/editor_timefx.cc:82 gtk_ardour/editor_timefx.cc:83 +#: gtk_ardour/editor_timefx.cc:84 gtk_ardour/editor_timefx.cc:85 +msgid "TimeStretchButton" +msgstr "TimeStretchButton" + +#: gtk_ardour/editor_timefx.cc:86 +msgid "TimeStretchProgress" +msgstr "TimeStretchProgress" + +#: gtk_ardour/editor_timefx.cc:151 +msgid "timestretch cannot be started - thread creation error" +msgstr "" + +#: gtk_ardour/export_dialog.cc:63 gtk_ardour/export_dialog.cc:410 +#: gtk_ardour/export_dialog.cc:947 gtk_ardour/export_dialog.cc:1189 +msgid "22.05kHz" +msgstr "22.05кГц" + +#: gtk_ardour/export_dialog.cc:64 gtk_ardour/export_dialog.cc:413 +#: gtk_ardour/export_dialog.cc:428 gtk_ardour/export_dialog.cc:949 +#: gtk_ardour/export_dialog.cc:1191 +msgid "44.1kHz" +msgstr "44.1кГц" + +#: gtk_ardour/export_dialog.cc:65 gtk_ardour/export_dialog.cc:416 +#: gtk_ardour/export_dialog.cc:951 gtk_ardour/export_dialog.cc:1193 +msgid "48kHz" +msgstr "48кГц" + +#: gtk_ardour/export_dialog.cc:66 gtk_ardour/export_dialog.cc:419 +#: gtk_ardour/export_dialog.cc:953 gtk_ardour/export_dialog.cc:1195 +msgid "88.2kHz" +msgstr "88.2кГц" + +#: gtk_ardour/export_dialog.cc:67 gtk_ardour/export_dialog.cc:422 +#: gtk_ardour/export_dialog.cc:955 gtk_ardour/export_dialog.cc:1197 +msgid "96kHz" +msgstr "96кГц" + +#: gtk_ardour/export_dialog.cc:68 gtk_ardour/export_dialog.cc:425 +#: gtk_ardour/export_dialog.cc:957 gtk_ardour/export_dialog.cc:1199 +msgid "192kHz" +msgstr "192кГц" + +#: gtk_ardour/export_dialog.cc:73 +msgid "best" +msgstr "выÑокое" + +#: gtk_ardour/export_dialog.cc:74 gtk_ardour/export_dialog.cc:964 +msgid "fastest" +msgstr "быÑтрое" + +#: gtk_ardour/export_dialog.cc:75 gtk_ardour/export_dialog.cc:966 +msgid "linear" +msgstr "линейное" + +#: gtk_ardour/export_dialog.cc:76 gtk_ardour/export_dialog.cc:968 +msgid "better" +msgstr "нормальное" + +#: gtk_ardour/export_dialog.cc:77 gtk_ardour/export_dialog.cc:970 +msgid "intermediate" +msgstr "Ñреднее" + +#: gtk_ardour/export_dialog.cc:83 gtk_ardour/export_dialog.cc:979 +msgid "Rectangular" +msgstr "Rectangular" + +#: gtk_ardour/export_dialog.cc:84 +msgid "Shaped Noise" +msgstr "Shaped Noise" + +#: gtk_ardour/export_dialog.cc:85 gtk_ardour/export_dialog.cc:981 +msgid "Triangular" +msgstr "Triangular" + +#: gtk_ardour/export_dialog.cc:90 gtk_ardour/utils.cc:336 +msgid "stereo" +msgstr "Ñтерео" + +#: gtk_ardour/export_dialog.cc:91 gtk_ardour/export_dialog.cc:497 +#: gtk_ardour/export_dialog.cc:929 gtk_ardour/export_dialog.cc:1219 +#: gtk_ardour/utils.cc:334 +msgid "mono" +msgstr "моно" + +#: gtk_ardour/export_dialog.cc:97 +msgid "CUE" +msgstr "" + +#: gtk_ardour/export_dialog.cc:98 +msgid "TOC" +msgstr "" + +#: gtk_ardour/export_dialog.cc:106 +msgid "FORMAT" +msgstr "ФОРМÐТ" + +#: gtk_ardour/export_dialog.cc:107 +msgid "SAMPLE RATE" +msgstr "ЧÐСТОТРДИСКРЕТИЗÐЦИИ" + +#: gtk_ardour/export_dialog.cc:108 +msgid "CONVERSION QUALITY" +msgstr "КÐЧЕСТВО ПРЕОБРÐЗОВÐÐИЯ" + +#: gtk_ardour/export_dialog.cc:109 +msgid "DITHER TYPE" +msgstr "ТИП ПОДМЕШИВÐЕМОГО ШУМÐ" + +#: gtk_ardour/export_dialog.cc:110 +#, fuzzy +msgid "CD MARKER FILE TYPE" +msgstr "ТИП ФÐЙЛÐ" + +#: gtk_ardour/export_dialog.cc:111 +msgid "CHANNELS" +msgstr "КÐÐÐЛЫ" + +#: gtk_ardour/export_dialog.cc:112 +msgid "FILE TYPE" +msgstr "ТИП ФÐЙЛÐ" + +#: gtk_ardour/export_dialog.cc:113 +msgid "SAMPLE FORMAT" +msgstr "РÐЗРЯДÐОСТЬ" + +#: gtk_ardour/export_dialog.cc:114 +msgid "SAMPLE ENDIANNESS" +msgstr "СВОЙСТВÐ" + +#: gtk_ardour/export_dialog.cc:115 +#, fuzzy +msgid "EXPORT CD MARKER FILE ONLY" +msgstr "ТИП ФÐЙЛÐ" + +#: gtk_ardour/export_dialog.cc:116 +msgid "EXPORT TO FILE" +msgstr "ЭКСПОРТ Ð’ ФÐЙЛ" + +#: gtk_ardour/export_dialog.cc:117 gtk_ardour/option_editor.cc:118 +#: gtk_ardour/option_editor.cc:119 +msgid "Browse" +msgstr "Обзор" + +#: gtk_ardour/export_dialog.cc:119 +msgid "Specific tracks ..." +msgstr "" + +#: gtk_ardour/export_dialog.cc:131 +msgid "ardour: export" +msgstr "ardour: ÑкÑпорт" + +#: gtk_ardour/export_dialog.cc:132 +msgid "ardour_export" +msgstr "ardour_ÑкÑпорт" + +#: gtk_ardour/export_dialog.cc:156 +#, fuzzy +msgid "Output" +msgstr "Выходов" + +#: gtk_ardour/export_dialog.cc:168 gtk_ardour/mixer_strip.cc:626 +msgid "Track" +msgstr "Трек" + +#: gtk_ardour/export_dialog.cc:287 +msgid "slereg" +msgstr "slereg" + +#: gtk_ardour/export_dialog.cc:658 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD toc file" +msgstr "" +"Редакор: не могу открыть \"%1\" как файл ÑкÑпорта маркеров Ð´Ð»Ñ CD-треков" + +#: gtk_ardour/export_dialog.cc:780 +#, fuzzy +msgid "Editor: cannot open \"%1\" as export file for CD cue file" +msgstr "" +"Редакор: не могу открыть \"%1\" как файл ÑкÑпорта маркеров Ð´Ð»Ñ CD-треков" + +#: gtk_ardour/export_dialog.cc:799 +msgid "WAV" +msgstr "" + +#: gtk_ardour/export_dialog.cc:1051 +msgid "Stop Export" +msgstr "ОÑтановить ÑкÑпорт" + +#: gtk_ardour/gain_automation_time_axis.cc:60 +#, fuzzy +msgid "add gain automation event" +msgstr "автомат" + +#: gtk_ardour/gain_meter.cc:68 +msgid "Cannot create slider pixmaps" +msgstr "" + +#: gtk_ardour/gain_meter.cc:83 +msgid "dbFS" +msgstr "" + +#: gtk_ardour/gain_meter.cc:84 gtk_ardour/gain_meter.cc:134 +#: gtk_ardour/gain_meter.cc:728 +msgid "pre" +msgstr "" + +#: gtk_ardour/gain_meter.cc:130 gtk_ardour/gain_meter.cc:724 +#, fuzzy +msgid "input" +msgstr "%1 вход" + +#: gtk_ardour/gain_meter.cc:138 gtk_ardour/gain_meter.cc:732 +#, fuzzy +msgid "post" +msgstr "порт" + +#: gtk_ardour/gain_meter.cc:146 +msgid "tupni" +msgstr "" + +#: gtk_ardour/gain_meter.cc:167 gtk_ardour/gain_meter.cc:470 +#: gtk_ardour/gain_meter.cc:492 gtk_ardour/gain_meter.cc:537 +#, fuzzy +msgid "-inf" +msgstr "в" + +#: gtk_ardour/imageframe_socket_handler.cc:127 +msgid "Image Compositor Socket has been shutdown/closed" +msgstr "" + +#: gtk_ardour/imageframe_time_axis.cc:295 +#, fuzzy +msgid "0.5 seconds" +msgstr "Минуты:Секунды" + +#: gtk_ardour/imageframe_time_axis.cc:296 gtk_ardour/marker_time_axis.cc:259 +#, fuzzy +msgid "1 seconds" +msgstr "Минуты:Секунды" + +#: gtk_ardour/imageframe_time_axis.cc:297 gtk_ardour/marker_time_axis.cc:260 +#, fuzzy +msgid "1.5 seconds" +msgstr "Минуты:Секунды" + +#: gtk_ardour/imageframe_time_axis.cc:298 gtk_ardour/marker_time_axis.cc:261 +#, fuzzy +msgid "2 seconds" +msgstr "Минуты:Секунды" + +#: gtk_ardour/imageframe_time_axis.cc:299 gtk_ardour/marker_time_axis.cc:262 +#, fuzzy +msgid "2.5 seconds" +msgstr "Минуты:Секунды" + +#: gtk_ardour/imageframe_time_axis.cc:300 gtk_ardour/marker_time_axis.cc:263 +#, fuzzy +msgid "3 seconds" +msgstr "Минуты:Секунды" + +#: gtk_ardour/imageframe_time_axis.cc:305 gtk_ardour/marker_time_axis.cc:268 +msgid "Duration (sec)" +msgstr "" + +#: gtk_ardour/imageframe_time_axis.cc:310 +#, fuzzy +msgid "Remove Frame" +msgstr "Удалить поле" + +#: gtk_ardour/imageframe_time_axis.cc:313 +#, fuzzy +msgid "Image Frame" +msgstr "Кадр" + +#: gtk_ardour/imageframe_time_axis.cc:314 gtk_ardour/marker_time_axis.cc:274 +#, fuzzy +msgid "Rename Track" +msgstr "Переименовать" + +#: gtk_ardour/io_selector.cc:64 +msgid "%1 input" +msgstr "%1 вход" + +#: gtk_ardour/io_selector.cc:66 +msgid "%1 output" +msgstr "%1 выход" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:103 +msgid "Inputs" +msgstr "Входов" + +#: gtk_ardour/io_selector.cc:141 gtk_ardour/route_params_ui.cc:104 +msgid "Outputs" +msgstr "Выходов" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Input" +msgstr "добавить вход" + +#: gtk_ardour/io_selector.cc:142 +#, fuzzy +msgid "Add Output" +msgstr "добавить выход" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Input" +msgstr "Удалить" + +#: gtk_ardour/io_selector.cc:143 +#, fuzzy +msgid "Remove Output" +msgstr "# Выходов" + +#: gtk_ardour/io_selector.cc:144 +#, fuzzy +msgid "Disconnect All" +msgstr "ОтÑоединить" + +#: gtk_ardour/io_selector.cc:158 +msgid "Available connections" +msgstr "ДоÑтупные ÑоединениÑ" + +#: gtk_ardour/io_selector.cc:424 gtk_ardour/io_selector.cc:636 +#: gtk_ardour/io_selector.cc:688 gtk_ardour/io_selector.cc:724 +msgid "port" +msgstr "порт" + +#: gtk_ardour/io_selector.cc:568 gtk_ardour/io_selector.cc:587 +msgid "There are no more JACK ports available." +msgstr "" + +#: gtk_ardour/io_selector.cc:790 +msgid "ardour: " +msgstr "ardour: " + +#: gtk_ardour/keyboard.cc:419 +msgid "KeyboardTarget: keyname \"%1\" is unknown." +msgstr "KeyboardTarget: \"%1\" - неизвеÑтное имÑ." + +#: gtk_ardour/keyboard.cc:645 +msgid "" +"Your system is completely broken - NumLock uses \"%1\"as its modifier. This " +"is madness - see the man page for xmodmap to find out how to fix this." +msgstr "" + +#: gtk_ardour/keyboard.cc:653 +msgid "" +"Your system generates \"%1\" when the NumLock key is pressed. This can cause " +"problems when editing so Ardour will use %2 to mean Meta rather than %1" +msgstr "" + +#: gtk_ardour/keyboard.cc:714 +msgid "You have %1 keys bound to \"mod1\"" +msgstr "Ð”Ð»Ñ \"mod1\" назначено кнопок: %1" + +#: gtk_ardour/keyboard.cc:729 +msgid "You have %1 keys bound to \"mod2\"" +msgstr "Ð”Ð»Ñ \"mod2\" назначено кнопок: %1" + +#: gtk_ardour/keyboard.cc:744 +msgid "You have %1 keys bound to \"mod3\"" +msgstr "Ð”Ð»Ñ \"mod3\" назначено кнопок: %1" + +#: gtk_ardour/keyboard.cc:759 +msgid "You have %1 keys bound to \"mod4\"" +msgstr "Ð”Ð»Ñ \"mod4\" назначено кнопок: %1" + +#: gtk_ardour/keyboard.cc:774 +msgid "You have %1 keys bound to \"mod5\"" +msgstr "Ð”Ð»Ñ \"mod5\" назначено кнопок: %1" + +#: gtk_ardour/keyboard_target.cc:72 +msgid "KeyboardTarget: empty string passed to add_binding." +msgstr "" + +#: gtk_ardour/keyboard_target.cc:78 +msgid "KeyboardTarget: no translation found for \"%1\"" +msgstr "KeyboardTarget: Ð´Ð»Ñ \"%1\" ÑопоÑтавление не найдено" + +#: gtk_ardour/keyboard_target.cc:83 +msgid "KeyboardTarget: unknown action \"%1\"" +msgstr "KeyboardTarget: \"%1\" - неизвеÑтное Ñобытие" + +#: gtk_ardour/keyboard_target.cc:248 +msgid "misformed binding node - ignored" +msgstr "неверное определение ÑвÑзи - пропущено" + +#: gtk_ardour/library_ui.cc:62 +msgid "Soundfile Library" +msgstr "Ðудио-библиотека" + +#: gtk_ardour/library_ui.cc:63 +msgid "Filesystem" +msgstr "" + +#: gtk_ardour/library_ui.cc:66 +msgid "Split Channels" +msgstr "" + +#: gtk_ardour/library_ui.cc:69 +msgid "ardour: soundfile selector" +msgstr "ardour: выбор файлов" + +#: gtk_ardour/library_ui.cc:430 +msgid "Add to Library..." +msgstr "" +"Добавить\n" +"в библиотеку..." + +#: gtk_ardour/library_ui.cc:431 +msgid "Remove..." +msgstr "Удалить..." + +#: gtk_ardour/library_ui.cc:432 +msgid "Find..." +msgstr "Ðайти..." + +#: gtk_ardour/library_ui.cc:433 +msgid "Add Folder" +msgstr "" +"Создать\n" +"папку" + +#: gtk_ardour/library_ui.cc:434 +msgid "Add audio file or directory" +msgstr "Добавить аудиофайл или каталог" + +#: gtk_ardour/library_ui.cc:713 +msgid "Importing" +msgstr "Импорт" + +#: gtk_ardour/library_ui.cc:748 +msgid "%1 not added to database" +msgstr "%1 не добавлен в базу" + +#: gtk_ardour/library_ui.cc:767 +msgid "Folder name:" +msgstr "Ð˜Ð¼Ñ Ð¿Ð°Ð¿ÐºÐ¸:" + +#: gtk_ardour/library_ui.cc:838 +msgid "Should not be reached" +msgstr "Станет недоÑтупен" + +#: gtk_ardour/library_ui.cc:940 gtk_ardour/library_ui.cc:1096 +msgid "file \"%1\" could not be opened" +msgstr "не удалоÑÑŒ открыть файл \"%1\" !" + +#: gtk_ardour/library_ui.cc:956 +msgid "Field" +msgstr "Критерий" + +#: gtk_ardour/library_ui.cc:957 +msgid "Value" +msgstr "Значение" + +#: gtk_ardour/library_ui.cc:973 +msgid "Stop" +msgstr "Стоп" + +#: gtk_ardour/library_ui.cc:974 +msgid "Add Field..." +msgstr "Добавить поле..." + +#: gtk_ardour/library_ui.cc:975 +msgid "Remove Field" +msgstr "Удалить поле" + +#: gtk_ardour/library_ui.cc:979 +msgid "Soundfile Info" +msgstr "Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ файле" + +#: gtk_ardour/library_ui.cc:1106 +msgid "file \"%1\" appears not to be an audio file" +msgstr "" + +#: gtk_ardour/library_ui.cc:1159 +#, fuzzy +msgid "Could not read file: %1 (%2)." +msgstr "Редактор: не удалоÑÑŒ открыть файл \"%1\" (%2)" + +#: gtk_ardour/library_ui.cc:1177 +msgid "Could not access soundfile: " +msgstr "Файл недоÑтупен: " + +#: gtk_ardour/library_ui.cc:1222 +msgid "Field name:" +msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»Ñ:" + +#: gtk_ardour/library_ui.cc:1275 gtk_ardour/library_ui.cc:1367 +msgid "Field value:" +msgstr "Значение полÑ:" + +#: gtk_ardour/library_ui.cc:1295 +msgid "Find" +msgstr "Ðайти" + +#: gtk_ardour/library_ui.cc:1296 +msgid "AND" +msgstr "И" + +#: gtk_ardour/library_ui.cc:1297 +msgid "OR" +msgstr "ИЛИ" + +#: gtk_ardour/library_ui.cc:1300 +msgid "ardour: locate soundfiles" +msgstr "ardour: раÑположение звуковых файлов" + +#: gtk_ardour/library_ui.cc:1426 +msgid "Results" +msgstr "Результаты" + +#: gtk_ardour/library_ui.cc:1427 +msgid "Uris" +msgstr "Uris" + +#: gtk_ardour/library_ui.cc:1439 +msgid "Create multi-channel region" +msgstr "" +"Создать\n" +"многоканальный" + +#: gtk_ardour/library_ui.cc:1442 +msgid "Ardour: Search Results" +msgstr "Ardour: ПоиÑк результатов" + +#: gtk_ardour/location_ui.cc:47 gtk_ardour/location_ui.cc:50 +msgid "Set" +msgstr "" + +#: gtk_ardour/location_ui.cc:48 gtk_ardour/location_ui.cc:51 +msgid "Go" +msgstr "" + +#: gtk_ardour/location_ui.cc:54 +msgid "CD" +msgstr "CD" + +#: gtk_ardour/location_ui.cc:55 +msgid "Hidden" +msgstr "Скрытый" + +#: gtk_ardour/location_ui.cc:57 +msgid "SCMS" +msgstr "" + +#: gtk_ardour/location_ui.cc:58 +msgid "Pre-Emphasis" +msgstr "" + +#: gtk_ardour/location_ui.cc:592 +msgid "Add New Location" +msgstr "Добавить новый интервал" + +#: gtk_ardour/location_ui.cc:593 +msgid "Add New Range" +msgstr "" + +#: gtk_ardour/location_ui.cc:597 +msgid "ardour: locations" +msgstr "ardour: интервалы" + +#: gtk_ardour/location_ui.cc:598 +msgid "ardour_locations" +msgstr "ardour_интервалы" + +#: gtk_ardour/location_ui.cc:629 +#, fuzzy +msgid "Location (CD Index) Markers" +msgstr "Маркеры интервалов" + +#: gtk_ardour/location_ui.cc:649 +msgid "Range (CD Track) Markers" +msgstr "" + +#: gtk_ardour/location_ui.cc:814 +msgid "add range marker" +msgstr "" + +#: gtk_ardour/main.cc:76 +msgid "ardour is killing itself for a clean exit\n" +msgstr "ardour: принудительное завершение работы\n" + +#: gtk_ardour/main.cc:85 +msgid "stopping user interface\n" +msgstr "завершение работы...\n" + +#: gtk_ardour/main.cc:104 +#, fuzzy, c-format +msgid "%d(%d): received signal %d\n" +msgstr "%d: принÑÑ‚ Ñигнал %d\n" + +#: gtk_ardour/main.cc:190 +msgid "cannot become new process group leader (%1)" +msgstr "" + +#: gtk_ardour/main.cc:217 +msgid "cannot setup signal handling for %1" +msgstr "cannot setup signal handling for %1" + +#: gtk_ardour/main.cc:228 +msgid "cannot set default signal mask (%1)" +msgstr "cannot set default signal mask (%1)" + +#: gtk_ardour/main.cc:253 +#, fuzzy +msgid "" +"Without a UI style file, ardour will look strange.\n" +" Please set ARDOUR_UI_RC to point to a valid UI style file" +msgstr "" +"ГрафичеÑий Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ardour будет выглÑдеть необычно\n" +"без файла определÑющего Ñтиль отображениÑ.\n" +"ПожалуйÑта, укажите его (файл) в переменной Ð¾ÐºÑ€ÑƒÐ¶ÐµÐ½Ð¸Ñ ARDOUR_UI_RC" + +#: gtk_ardour/main.cc:292 +msgid "" +"Ardour could not connect to JACK.\n" +"There are several possible reasons:\n" +"\n" +"1) JACK is not running.\n" +"2) JACK is running as another user, perhaps root.\n" +"3) There is already another client called \"ardour\".\n" +"\n" +"Please consider the possibilities, and perhaps (re)start JACK." +msgstr "" +"Ardour не удаётÑÑ ÑƒÑтановить Ñоединение Ñ Ñервером JACK.\n" +"СущеÑтвует неÑколько возможных причин:\n" +"\n" +"1) Сервер JACK не запущен.\n" +"2) Сервер JACK запущен Ñ Ð¿Ñ€Ð°Ð²Ð°Ð¼Ð¸ другого пользователÑ, возможно root.\n" +"3) Уже ÑущеÑтвует клиент Ñервера JACK Ñ Ð¸Ð¼ÐµÐ½ÐµÐ¼ \"ardour\".\n" +"\n" +"ПожалуйÑта, проверьте вÑе варианты, возможно потребуетÑÑ (пере)запуÑк JACK." + +#: gtk_ardour/main.cc:305 +msgid "ardour: unplugged" +msgstr "ardour: нет ÑоединениÑ" + +#: gtk_ardour/main.cc:363 +msgid "Ardour/GTK " +msgstr "Ardour/GTK " + +#: gtk_ardour/main.cc:365 +msgid "" +"\n" +" (built using " +msgstr "" + +#: gtk_ardour/main.cc:369 +#, fuzzy +msgid " with libardour " +msgstr " работает Ñ libardour " + +#: gtk_ardour/main.cc:374 +msgid " and GCC version " +msgstr "" + +#: gtk_ardour/main.cc:384 +#, fuzzy +msgid "Copyright (C) 1999-2005 Paul Davis" +msgstr "ÐвторÑкое право 1999-2004 Paul Davis" + +#: gtk_ardour/main.cc:385 +msgid "" +"Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel " +"Baker" +msgstr "" + +#: gtk_ardour/main.cc:387 +msgid "Ardour comes with ABSOLUTELY NO WARRANTY" +msgstr "Ardour раÑпроÑтранÑетÑÑ Ð‘Ð•Ð— ВСЯКИХ ГÐРÐÐТИЙ" + +#: gtk_ardour/main.cc:388 +msgid "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." +msgstr "" + +#: gtk_ardour/main.cc:389 +msgid "This is free software, and you are welcome to redistribute it " +msgstr "Это Ñвободное программное обеÑпечение, Ð’Ñ‹ можете раÑпроÑтранÑть его" + +#: gtk_ardour/main.cc:390 +#, fuzzy +msgid "under certain conditions; see the source for copying conditions." +msgstr "на определённых уÑловиÑÑ…; подробнее об Ñтом читайте в файле COPYING." + +#: gtk_ardour/main.cc:399 +msgid "could not create ARDOUR GUI" +msgstr "не удалоÑÑŒ Ñоздать графичеÑкий Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ Ð´Ð»Ñ ARDOUR" + +#: gtk_ardour/main.cc:419 +msgid "Could not connect to JACK server as \"%1\"" +msgstr "Ðе удалоÑÑŒ ÑоединитьÑÑ Ñ Ñервером JACK как \"%1\"" + +#: gtk_ardour/main.cc:424 +msgid "could not initialize Ardour." +msgstr "не удалоÑÑŒ запуÑтить Ardour." + +#: gtk_ardour/main.cc:435 +msgid "could not load command line session \"%1\"" +msgstr "не удалоÑÑŒ загрузить ÑеÑÑию \"%1\", указанную в командной Ñтроке" + +#: gtk_ardour/main.cc:455 +msgid "" +"\n" +"\n" +"A session named \"%1\" already exists.\n" +"To avoid this message, start ardour as \"ardour %1" +msgstr "" + +#: gtk_ardour/main.cc:466 +msgid "" +"\n" +"\n" +"No session named \"%1\" exists.\n" +"To create it from the command line, start ardour as \"ardour --new %1" +msgstr "" + +#: gtk_ardour/marker.cc:354 +#, fuzzy +msgid "MarkerText" +msgstr "маркерам" + +#: gtk_ardour/marker_time_axis.cc:271 +#, fuzzy +msgid "Remove Marker" +msgstr "Удалить поле" + +#: gtk_ardour/marker_time_axis.cc:273 +#, fuzzy +msgid "Marker" +msgstr "маркерам" + +#: gtk_ardour/meter_bridge.cc:74 +msgid "ardour: meter bridge" +msgstr "ardour: индикатор уровнÑ" + +#: gtk_ardour/meter_bridge.cc:75 +msgid "ardour_meter_bridge" +msgstr "ardour_индикатор_уровнÑ" + +#: gtk_ardour/meter_bridge_strip.cc:79 gtk_ardour/meter_bridge_strip.cc:93 +#, c-format +msgid "# of %u-sample overs" +msgstr "" + +#: gtk_ardour/meter_bridge_strip.cc:219 +msgid "New name for meter:" +msgstr "Ðовое Ð¸Ð¼Ñ Ð¸Ð½Ð´Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð°:" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:507 +#: gtk_ardour/region_editor.cc:45 +msgid "mute" +msgstr "тихо" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:508 +msgid "solo" +msgstr "Ñоло" + +#: gtk_ardour/mixer_strip.cc:117 gtk_ardour/mixer_strip.cc:506 +msgid "RECORD" +msgstr "ЗÐПИСЬ" + +#: gtk_ardour/mixer_strip.cc:128 gtk_ardour/mixer_strip.cc:514 +msgid "polarity" +msgstr "полÑрноÑть" + +#: gtk_ardour/mixer_strip.cc:129 gtk_ardour/mixer_strip.cc:509 +msgid "comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:152 gtk_ardour/mixer_strip.cc:810 +msgid "INPUT" +msgstr "ВХОД" + +#: gtk_ardour/mixer_strip.cc:157 gtk_ardour/mixer_strip.cc:831 +msgid "OUTPUT" +msgstr "ВЫХОД" + +#: gtk_ardour/mixer_strip.cc:173 +#, fuzzy +msgid "Pan automation mode" +msgstr "автомат" + +#: gtk_ardour/mixer_strip.cc:174 +#, fuzzy +msgid "Gain automation mode" +msgstr "автомат" + +#: gtk_ardour/mixer_strip.cc:176 +#, fuzzy +msgid "Pan automation type" +msgstr "автомат" + +#: gtk_ardour/mixer_strip.cc:177 +#, fuzzy +msgid "Gain automation type" +msgstr "автомат" + +#: gtk_ardour/mixer_strip.cc:220 gtk_ardour/mixer_strip.cc:232 +#: gtk_ardour/mixer_strip.cc:979 +msgid "trim" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:221 gtk_ardour/mixer_strip.cc:233 +#: gtk_ardour/mixer_strip.cc:983 +msgid "abs" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:240 +#, fuzzy +msgid "gain automation mode" +msgstr "автомат" + +#: gtk_ardour/mixer_strip.cc:241 +#, fuzzy +msgid "pan automation mode" +msgstr "автомат" + +#: gtk_ardour/mixer_strip.cc:242 +#, fuzzy +msgid "gain automation state" +msgstr "автомат" + +#: gtk_ardour/mixer_strip.cc:243 +#, fuzzy +msgid "pan automation state" +msgstr "автомат" + +#: gtk_ardour/mixer_strip.cc:259 +msgid "varispeed" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:281 gtk_ardour/mixer_strip.cc:1174 +msgid "click to add/edit comments" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:463 +msgid "unknown strip width \"%1\" in XML GUI information" +msgstr "неизвеÑÑ‚Ð½Ð°Ñ ÑˆÐ¸Ñ€Ð¸Ð½Ð° трека \"%1\" в XML опиÑании" + +#: gtk_ardour/mixer_strip.cc:522 +msgid "REC" +msgstr "ЗÐП" + +#: gtk_ardour/mixer_strip.cc:525 +#, fuzzy +msgid "cmt" +msgstr "вырезать" + +#: gtk_ardour/mixer_strip.cc:530 +msgid "pol" +msgstr "пол" + +#: gtk_ardour/mixer_strip.cc:562 gtk_ardour/mixer_strip.cc:620 +#: gtk_ardour/redirect_box.cc:1180 +msgid "Not connected to JACK - no I/O changes are possible" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:651 gtk_ardour/mixer_strip.cc:667 +msgid "could not register new ports required for that connection" +msgstr "" + +#: gtk_ardour/mixer_strip.cc:813 +msgid "IN" +msgstr "Ð’Ð¥" + +#: gtk_ardour/mixer_strip.cc:834 +msgid "OUT" +msgstr "ВЫХ" + +#: gtk_ardour/mixer_strip.cc:950 +msgid "aplay" +msgstr "авоÑпр" + +#: gtk_ardour/mixer_strip.cc:956 +#, fuzzy +msgid "awrite" +msgstr "запиÑÑŒ" + +#: gtk_ardour/mixer_strip.cc:1134 +#, fuzzy +msgid ": comment editor" +msgstr "ИнтерфейÑ: не удалоÑÑŒ инициализировать редактор" + +#: gtk_ardour/mixer_strip.cc:1205 gtk_ardour/mixer_strip.cc:1224 +msgid "no group" +msgstr "нет группы" + +#: gtk_ardour/mixer_strip.cc:1227 +msgid "~G" +msgstr "нГр" + +#: gtk_ardour/mixer_ui.cc:52 +msgid "Strips" +msgstr "Каналы" + +#: gtk_ardour/mixer_ui.cc:56 +msgid "Snapshots" +msgstr "Снимки" + +#: gtk_ardour/mixer_ui.cc:61 +msgid "***" +msgstr "***" + +#: gtk_ardour/mixer_ui.cc:62 gtk_ardour/tempo_dialog.cc:17 +#: gtk_ardour/tempo_dialog.cc:34 gtk_ardour/tempo_dialog.cc:144 +#: gtk_ardour/tempo_dialog.cc:162 +msgid "Bar" +msgstr "Такт" + +#: gtk_ardour/mixer_ui.cc:121 +msgid "Mix Groups" +msgstr "Mix группы" + +#: gtk_ardour/mixer_ui.cc:191 gtk_ardour/mixer_ui.cc:373 +msgid "ardour: mixer" +msgstr "ardour: микшер" + +#: gtk_ardour/mixer_ui.cc:192 +msgid "ardour_mixer" +msgstr "ardour_микшер" + +#: gtk_ardour/mixer_ui.cc:342 +msgid "ardour: mixer: " +msgstr "ardour: микшер: " + +#: gtk_ardour/mixer_ui.cc:641 +msgid "signal" +msgstr "Ñигнал" + +#: gtk_ardour/mixer_ui.cc:672 +msgid "Show All AudioTrack MixerStrips" +msgstr "Показать вÑе каналы аудиотреков" + +#: gtk_ardour/mixer_ui.cc:673 +msgid "Hide All AudioTrack MixerStrips" +msgstr "Скрыть вÑе каналы аудиотреков" + +#: gtk_ardour/mixer_ui.cc:674 +msgid "Show All AudioBus MixerStrips" +msgstr "Показать вÑе каналы аудиошин" + +#: gtk_ardour/mixer_ui.cc:675 +msgid "Hide All AudioBus MixerStrips" +msgstr "Скрыть вÑе каналы аудиошин" + +#: gtk_ardour/mixer_ui.cc:687 +msgid "track display list item for renamed strip not found!" +msgstr "" + +#: gtk_ardour/mixer_ui.cc:700 +msgid "Name for new mix group" +msgstr "Ð˜Ð¼Ñ Ð½Ð¾Ð²Ð¾Ð¹ mix группы" + +#: gtk_ardour/new_session_dialog.cc:39 +msgid "Session name:" +msgstr "Ð˜Ð¼Ñ ÑеÑÑии:" + +#: gtk_ardour/new_session_dialog.cc:39 +msgid "Create" +msgstr "Создать" + +#: gtk_ardour/new_session_dialog.cc:40 +msgid "use control outs" +msgstr "иÑпользовать контрольные выходы" + +#: gtk_ardour/new_session_dialog.cc:41 +msgid "use master outs" +msgstr "иÑпользовать маÑтер-выходы" + +#: gtk_ardour/new_session_dialog.cc:42 +#, fuzzy +msgid "automatically connect track inputs to physical ports" +msgstr "автоматичеÑкое подключение треков ко входам" + +#: gtk_ardour/new_session_dialog.cc:43 +#, fuzzy +msgid "automatically connect track outputs to master outs" +msgstr "автоматичеÑкое подключение треков к маÑтер-выходам" + +#: gtk_ardour/new_session_dialog.cc:44 +#, fuzzy +msgid "automatically connect track outputs to physical ports" +msgstr "автоматичеÑкое подключение треков к выходам" + +#: gtk_ardour/new_session_dialog.cc:45 +msgid "manually connect track outputs" +msgstr "ручное подключение треков к выходам" + +#: gtk_ardour/new_session_dialog.cc:50 +msgid "Advanced..." +msgstr "Дополнительно..." + +#: gtk_ardour/new_session_dialog.cc:52 +msgid "show again" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:55 +msgid "Hardware Inputs: use" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:56 +msgid "Hardware Outputs: use" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:62 +msgid "new session setup" +msgstr "наÑтройки новой ÑеÑÑии" + +#: gtk_ardour/new_session_dialog.cc:63 +msgid "ardour_new_session" +msgstr "ardour_новаÑ_ÑеÑÑиÑ" + +#: gtk_ardour/new_session_dialog.cc:72 +msgid "This session will playback and record at %1 Hz" +msgstr "" +"Эта ÑеÑÑÐ¸Ñ Ð±ÑƒÐ´ÐµÑ‚ запиÑыватьÑÑ Ð¸ воÑпроизводитьÑÑ\n" +"Ñ Ñ‡Ð°Ñтотой диÑкретизации %1 Гц" + +#: gtk_ardour/new_session_dialog.cc:74 +msgid "" +"This rate is set by JACK and cannot be changed.\n" +"If you want to use a different sample rate\n" +"please exit and restart JACK" +msgstr "" +"Этот параметр уÑтанавливаетÑÑ Ñервером JACK и не может быть изменён.\n" +"ЕÑли вы хотите иÑпользовать другую чаÑтоту диÑкретизации,\n" +"вам необходимо закрыть Ardour и перезапуÑтить JACK" + +#: gtk_ardour/new_session_dialog.cc:155 +#, fuzzy +msgid "Session template" +msgstr "иÑпользовать имеющийÑÑ ÑˆÐ°Ð±Ð»Ð¾Ð½" + +#: gtk_ardour/new_session_dialog.cc:177 gtk_ardour/tempo_dialog.cc:20 +#: gtk_ardour/tempo_dialog.cc:37 gtk_ardour/tempo_dialog.cc:146 +#: gtk_ardour/tempo_dialog.cc:164 +msgid "Location" +msgstr "РаÑположение" + +#: gtk_ardour/new_session_dialog.cc:178 +msgid "Configuration" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:269 +msgid "blank" +msgstr "пуÑтой" + +#: gtk_ardour/new_session_dialog.cc:328 +msgid "No template - create tracks/busses manually" +msgstr "" + +#: gtk_ardour/new_session_dialog.cc:337 +#, fuzzy +msgid "No template" +msgstr "-шаблон" + +#: gtk_ardour/option_editor.cc:48 +#, fuzzy +msgid "Internal" +msgstr "внутренний" + +#: gtk_ardour/option_editor.cc:49 +#, fuzzy +msgid "Slave to MTC" +msgstr "Передача MTC" + +#: gtk_ardour/option_editor.cc:50 +msgid "Sync with JACK" +msgstr "" + +#: gtk_ardour/option_editor.cc:51 +msgid "never used but stops crashes" +msgstr "" + +#: gtk_ardour/option_editor.cc:56 +#, fuzzy +msgid "Later regions are higher" +msgstr "ОпуÑтить облаÑть на один Ñлой" + +#: gtk_ardour/option_editor.cc:57 +msgid "Most recently added/moved/trimmed regions are higher" +msgstr "" + +#: gtk_ardour/option_editor.cc:58 +#, fuzzy +msgid "Most recently added regions are higher" +msgstr "ОпуÑтить облаÑть на один Ñлой" + +#: gtk_ardour/option_editor.cc:63 +#, fuzzy +msgid "Span entire region overlap" +msgstr "ПоднÑть облаÑть на один Ñлой" + +#: gtk_ardour/option_editor.cc:64 +msgid "Short fades at the start of the overlap" +msgstr "" + +#: gtk_ardour/option_editor.cc:82 +#, fuzzy +msgid "Automatically create crossfades" +msgstr "ÐвтоматичеÑкий кроÑÑфейд на перекрытии" + +#: gtk_ardour/option_editor.cc:83 +msgid "New full-overlap crossfades are unmuted" +msgstr "" + +#: gtk_ardour/option_editor.cc:84 +#, fuzzy +msgid "Region layering mode" +msgstr "оконч. облаÑтей" + +#: gtk_ardour/option_editor.cc:85 +#, fuzzy +msgid "Crossfade model" +msgstr "КроÑÑфейд" + +#: gtk_ardour/option_editor.cc:90 +msgid "Latched solo" +msgstr "" + +#: gtk_ardour/option_editor.cc:91 +msgid "Solo via bus" +msgstr "" + +#: gtk_ardour/option_editor.cc:96 +#, fuzzy +msgid "Show waveforms while recording" +msgstr "Отображать форму Ñигнала" + +#: gtk_ardour/option_editor.cc:97 +msgid "Narrow mixer strips" +msgstr "Узкие каналы микшера" + +#: gtk_ardour/option_editor.cc:98 +msgid "Show measure lines" +msgstr "Показывать линии тактов" + +#: gtk_ardour/option_editor.cc:99 +msgid "Follow playhead" +msgstr "Следовать за указателем" + +#: gtk_ardour/option_editor.cc:103 +msgid "Send MTC" +msgstr "Передача MTC" + +#: gtk_ardour/option_editor.cc:104 +msgid "Send MMC" +msgstr "Передача MMC" + +#: gtk_ardour/option_editor.cc:105 +msgid "JACK time master" +msgstr "JACK-Ñчётчик - маÑтер" + +#: gtk_ardour/option_editor.cc:107 +#, fuzzy +msgid "SMPTE offset is negative" +msgstr "Смещение SMPTE" + +#: gtk_ardour/option_editor.cc:111 +msgid "Send MIDI parameter feedback" +msgstr "" + +#: gtk_ardour/option_editor.cc:112 +msgid "MIDI parameter control" +msgstr "" + +#: gtk_ardour/option_editor.cc:113 +#, fuzzy +msgid "MMC control" +msgstr "MMC порт" + +#: gtk_ardour/option_editor.cc:131 +#, fuzzy +msgid "Auto-connect new track inputs to hardware" +msgstr "ÐвтоподÑоединение новых треков" + +#: gtk_ardour/option_editor.cc:132 +#, fuzzy +msgid "Auto-connect new track outputs to hardware" +msgstr "ÐвтоподÑоединение новых треков" + +#: gtk_ardour/option_editor.cc:133 +#, fuzzy +msgid "Auto-connect new track outputs to master bus" +msgstr "автоматичеÑкое подключение треков к маÑтер-выходам" + +#: gtk_ardour/option_editor.cc:134 +#, fuzzy +msgid "Manually connect new track outputs" +msgstr "ручное подключение треков к выходам" + +#: gtk_ardour/option_editor.cc:135 +msgid "Use Hardware Monitoring" +msgstr "Ðппаратный контроль" + +#: gtk_ardour/option_editor.cc:136 +msgid "Use Software Monitoring" +msgstr "ИÑпользовать программный контроль" + +#: gtk_ardour/option_editor.cc:137 +msgid "Stop plugins with transport" +msgstr "ОÑтанавливать модули (plugins) вмеÑте Ñ Ñ‚Ñ€Ð°Ð½Ñпортом" + +#: gtk_ardour/option_editor.cc:138 +msgid "Run plugins while recording" +msgstr "ИÑпользовать модули (plugins) во Ð²Ñ€ÐµÐ¼Ñ Ð·Ð°Ð¿Ð¸Ñи" + +#: gtk_ardour/option_editor.cc:139 +#, fuzzy +msgid "Verify remove last capture" +msgstr "Удалить поÑледнюю запиÑÑŒ" + +#: gtk_ardour/option_editor.cc:140 +msgid "Stop recording on xrun" +msgstr "ОÑтановить запиÑÑŒ при потере отÑчётов" + +#: gtk_ardour/option_editor.cc:141 +msgid "Stop transport at end of session" +msgstr "ОÑтанавливать транÑпорт в конце ÑеÑÑии" + +#: gtk_ardour/option_editor.cc:142 +msgid "Debug keyboard events" +msgstr "Отладка наÑтроек клавиатуры" + +#: gtk_ardour/option_editor.cc:143 +msgid "-12dB gain reduction for ffwd/rew" +msgstr "" + +#: gtk_ardour/option_editor.cc:152 +msgid "ardour: options editor" +msgstr "adour: редактор параметров" + +#: gtk_ardour/option_editor.cc:153 +msgid "ardour_option_editor" +msgstr "adour_редактор_параметров" + +#: gtk_ardour/option_editor.cc:183 +msgid "Misc" +msgstr "Прочее" + +#: gtk_ardour/option_editor.cc:184 +msgid "Sync" +msgstr "Синхр." + +#: gtk_ardour/option_editor.cc:185 +msgid "Paths/Files" +msgstr "Пути/Файлы" + +#: gtk_ardour/option_editor.cc:186 +msgid "Display" +msgstr "Экран" + +#: gtk_ardour/option_editor.cc:187 +msgid "Kbd/Mouse" +msgstr "Клавиатура/Мышь" + +#: gtk_ardour/option_editor.cc:188 +msgid "Click" +msgstr "Метроном" + +#: gtk_ardour/option_editor.cc:190 +msgid "Layers & Fades" +msgstr "" + +#: gtk_ardour/option_editor.cc:195 +msgid "MIDI" +msgstr "MIDI" + +#: gtk_ardour/option_editor.cc:268 +msgid "24 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:270 +msgid "25 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:272 +msgid "30 FPS" +msgstr "" + +#: gtk_ardour/option_editor.cc:278 +msgid "30 FPS drop" +msgstr "" + +#: gtk_ardour/option_editor.cc:362 gtk_ardour/option_editor.cc:379 +#: gtk_ardour/option_editor.cc:715 gtk_ardour/option_editor.cc:736 +#: gtk_ardour/option_editor.cc:778 gtk_ardour/option_editor.cc:800 +msgid "Medium" +msgstr "" + +#: gtk_ardour/option_editor.cc:366 gtk_ardour/option_editor.cc:738 +#: gtk_ardour/option_editor.cc:804 +#, fuzzy +msgid "Faster" +msgstr "Затухание" + +#: gtk_ardour/option_editor.cc:376 gtk_ardour/option_editor.cc:714 +#: gtk_ardour/option_editor.cc:776 +#, fuzzy +msgid "Short" +msgstr "порт" + +#: gtk_ardour/option_editor.cc:382 gtk_ardour/option_editor.cc:716 +#: gtk_ardour/option_editor.cc:780 +msgid "Long" +msgstr "" + +#: gtk_ardour/option_editor.cc:396 +msgid "Broadcast WAVE/floating point" +msgstr "Broadcast WAVE/Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰Ð°Ñ Ñ‚Ð¾Ñ‡ÐºÐ°" + +#: gtk_ardour/option_editor.cc:397 +msgid "WAVE/floating point" +msgstr "WAVE/Ð¿Ð»Ð°Ð²Ð°ÑŽÑ‰Ð°Ñ Ñ‚Ð¾Ñ‡ÐºÐ°" + +#: gtk_ardour/option_editor.cc:417 +msgid "session RAID path" +msgstr "путь к файлам RAID ÑеÑÑий" + +#: gtk_ardour/option_editor.cc:422 +msgid "Native Format" +msgstr "Внутренний формат" + +#: gtk_ardour/option_editor.cc:454 gtk_ardour/option_editor.cc:460 +#: gtk_ardour/option_editor.cc:1382 gtk_ardour/option_editor.cc:1409 +msgid "internal" +msgstr "внутренний" + +#: gtk_ardour/option_editor.cc:537 +msgid "Short crossfade length (msecs)" +msgstr "" + +#: gtk_ardour/option_editor.cc:710 +msgid "Meter Peak Hold" +msgstr "" + +#: gtk_ardour/option_editor.cc:730 +msgid "Meter Falloff" +msgstr "" + +#: gtk_ardour/option_editor.cc:847 +msgid "Positional Sync" +msgstr "" + +#: gtk_ardour/option_editor.cc:902 +msgid "SMPTE Frames/second" +msgstr "SMPTE Кадры/Секунды" + +#: gtk_ardour/option_editor.cc:903 +msgid "SMPTE Offset" +msgstr "Смещение SMPTE" + +#: gtk_ardour/option_editor.cc:1006 gtk_ardour/option_editor.cc:1013 +#: gtk_ardour/option_editor.cc:1016 gtk_ardour/option_editor.cc:1211 +#, fuzzy +msgid "online" +msgstr "линейное" + +#: gtk_ardour/option_editor.cc:1013 gtk_ardour/option_editor.cc:1014 +#: gtk_ardour/option_editor.cc:1208 +#, fuzzy +msgid "offline" +msgstr "линейное" + +#: gtk_ardour/option_editor.cc:1319 +msgid "Use as click" +msgstr "ИÑпользовать как щелчок метронома" + +#: gtk_ardour/option_editor.cc:1344 +msgid "Use as click emphasis" +msgstr "ИÑпользовать как акцентирующий щелчок метронома" + +#: gtk_ardour/option_editor.cc:1478 +msgid "--unknown--" +msgstr "--неизвеÑтный--" + +#: gtk_ardour/option_editor.cc:1595 +msgid "Click audio file" +msgstr "Файл щелчков метронома" + +#: gtk_ardour/option_editor.cc:1601 +msgid "Click emphasis audiofile" +msgstr "Файл акцентирующих щелчков метронома" + +#: gtk_ardour/option_editor.cc:1638 +msgid "" +"The auditioner is a dedicated mixer strip used\n" +"for listening to specific regions outside the context\n" +"of the overall mix. It can be connected just like any\n" +"other mixer strip." +msgstr "" +"Контрольный канал - Ñто Ñпециальный канал микшера\n" +"предназначенный Ð´Ð»Ñ Ð¿Ñ€Ð¾ÑÐ»ÑƒÑˆÐ¸Ð²Ð°Ð½Ð¸Ñ Ð¾Ð¿Ñ€ÐµÐ´ÐµÐ»Ñ‘Ð½Ð½Ñ‹Ñ… облаÑтей\n" +"вне общего контекÑта микÑа. Его можно Ñоединить как любой\n" +"другой канал микшера." + +#: gtk_ardour/option_editor.cc:1887 +msgid "Edit using" +msgstr "Редактировать Ñочетание" + +#: gtk_ardour/option_editor.cc:1894 gtk_ardour/option_editor.cc:1924 +msgid "+ button" +msgstr "+ клавиша" + +#: gtk_ardour/option_editor.cc:1917 +msgid "Delete using" +msgstr "Удалить Ñочетание" + +#: gtk_ardour/option_editor.cc:1947 +msgid "Ignore snap using" +msgstr "Ðе иÑпользовать \"Ñнимки\"" + +#: gtk_ardour/opts.cc:46 +msgid "Usage: " +msgstr "ИÑпользование: " + +#: gtk_ardour/opts.cc:47 +msgid " -v, --version Show version information\n" +msgstr " -v, --version Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾ верÑии программы\n" + +#: gtk_ardour/opts.cc:48 +msgid " -h, --help Print this message\n" +msgstr " -h, --help Показать Ñто Ñообщение\n" + +#: gtk_ardour/opts.cc:49 +msgid "" +" -b, --bindings Print all possible keyboard binding " +"names\n" +msgstr "" +" -b, --bindings Показать вÑе доÑтупные \"горÑчие\" " +"клавиши\n" + +#: gtk_ardour/opts.cc:50 +#, fuzzy +msgid " -n, --show-splash Show splash screen\n" +msgstr " -n, --no-splash Ðе показывать заÑтавку\n" + +#: gtk_ardour/opts.cc:51 +#, fuzzy +msgid "" +" -c, --name name Use a specific jack client name, default " +"is ardour\n" +msgstr "" +" -c, --jack-client-name Ð¸Ð¼Ñ Ð˜Ñпользовать другое Ð¸Ð¼Ñ jack-клиента, " +"ardour по умолчанию\n" + +#: gtk_ardour/opts.cc:52 +#, fuzzy +msgid "" +" -N, --new session-name Create a new session from the command " +"line\n" +msgstr "" +" [имÑ-ÑеÑÑии] Загрузить ÑеÑÑию Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ñ‹Ð¼ именем\n" + +#: gtk_ardour/opts.cc:53 +msgid "" +" -o, --use-hw-optimizations Try to use h/w specific optimizations\n" +msgstr "" + +#: gtk_ardour/opts.cc:55 +#, fuzzy +msgid " -V, --novst Do not use VST support\n" +msgstr " -n, --no-splash Ðе показывать заÑтавку\n" + +#: gtk_ardour/opts.cc:57 +msgid " [session-name] Name of session to load\n" +msgstr "" +" [имÑ-ÑеÑÑии] Загрузить ÑеÑÑию Ñ ÑƒÐºÐ°Ð·Ð°Ð½Ð½Ñ‹Ð¼ именем\n" + +#: gtk_ardour/opts.cc:58 +msgid " -C, --curvetest filename Curve algorithm debugger\n" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:58 +msgid "You can't graphically edit panning of more than stream" +msgstr "" + +#: gtk_ardour/pan_automation_time_axis.cc:78 +#, fuzzy +msgid "add pan automation event" +msgstr "автомат" + +#: gtk_ardour/panner2d.cc:581 gtk_ardour/panner_ui.cc:441 +#, fuzzy +msgid "Bypass" +msgstr "обход" + +#: gtk_ardour/panner_ui.cc:90 gtk_ardour/panner_ui.cc:222 +#, fuzzy +msgid "link" +msgstr "в" + +#: gtk_ardour/panner_ui.cc:103 +msgid "panning link control" +msgstr "" + +#: gtk_ardour/panner_ui.cc:105 +msgid "panning link direction" +msgstr "" + +#: gtk_ardour/panner_ui.cc:232 +msgid "L" +msgstr "" + +#: gtk_ardour/panner_ui.cc:344 +#, c-format +msgid "panner for channel %u" +msgstr "" + +#: gtk_ardour/panner_ui.cc:451 +#, fuzzy +msgid "Reset all" +msgstr "ОгромнаÑ" + +#: gtk_ardour/playlist_selector.cc:46 +msgid "Playlists grouped by track" +msgstr "" + +#: gtk_ardour/playlist_selector.cc:53 +#, fuzzy +msgid "close" +msgstr "Закрыть" + +#: gtk_ardour/playlist_selector.cc:59 +#, fuzzy +msgid "ardour: playlists" +msgstr "ardour: модули (plugins)" + +#: gtk_ardour/playlist_selector.cc:104 +#, fuzzy +msgid "ardour: playlist for " +msgstr "ardour: редактор: " + +#: gtk_ardour/playlist_selector.cc:122 +#, fuzzy +msgid "Other tracks" +msgstr "Скрыть трек" + +#: gtk_ardour/playlist_selector.cc:138 +msgid "unassigned" +msgstr "" + +#: gtk_ardour/plugin_selector.cc:41 +msgid "Available LADSPA plugins" +msgstr "ДоÑтупные LADSPA модули" + +#: gtk_ardour/plugin_selector.cc:42 +msgid "Type" +msgstr "Тип" + +#: gtk_ardour/plugin_selector.cc:43 gtk_ardour/plugin_selector.cc:51 +msgid "# Inputs" +msgstr "# Входов" + +#: gtk_ardour/plugin_selector.cc:44 gtk_ardour/plugin_selector.cc:52 +msgid "# Outputs" +msgstr "# Выходов" + +#: gtk_ardour/plugin_selector.cc:50 +#, fuzzy +msgid "Available VST plugins" +msgstr "ДоÑтупные LADSPA модули" + +#: gtk_ardour/plugin_selector.cc:58 +msgid "To be added" +msgstr "Добавлено" + +#: gtk_ardour/plugin_selector.cc:72 +msgid "ardour: plugins" +msgstr "ardour: модули (plugins)" + +#: gtk_ardour/plugin_selector.cc:82 +msgid "Add a plugin to the effect list" +msgstr "Добавить модуль в ÑпиÑок Ñффектов" + +#: gtk_ardour/plugin_selector.cc:84 +msgid "Remove a plugin from the effect list" +msgstr "Удалить модуль из ÑпиÑка Ñффектов" + +#: gtk_ardour/plugin_selector.cc:88 +msgid "Update" +msgstr "Обновить" + +#: gtk_ardour/plugin_selector.cc:89 +msgid "Update available plugins" +msgstr "Обновить доÑтупные модули" + +#: gtk_ardour/plugin_selector.cc:110 +#, fuzzy +msgid "LADSPA" +msgstr "ADAT" + +#: gtk_ardour/plugin_selector.cc:113 +#, fuzzy +msgid "VST" +msgstr "УСТÐÐОВИТЬ" + +#: gtk_ardour/plugin_ui.cc:83 +msgid "" +"unknown type of editor-supplying plugin (note: no VST support in this " +"version of ardour)" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:269 +msgid "Plugin Editor: could not build control element for port %1" +msgstr "Редактор модулей: невозможно Ñоздать Ñффект Ð´Ð»Ñ Ð¿Ð¾Ñ€Ñ‚Ð° %1" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "in" +msgstr "в" + +#: gtk_ardour/plugin_ui.cc:367 +msgid "ins" +msgstr "вÑÑ‚" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "out" +msgstr "выход" + +#: gtk_ardour/plugin_ui.cc:368 +msgid "outs" +msgstr "выходы" + +#: gtk_ardour/plugin_ui.cc:382 +#, fuzzy +msgid "automation control" +msgstr "автомат" + +#: gtk_ardour/plugin_ui.cc:869 +#, fuzzy +msgid "save" +msgstr "Сохранить" + +#: gtk_ardour/plugin_ui.cc:870 +msgid "bypass" +msgstr "обход" + +#: gtk_ardour/plugin_ui.cc:892 +msgid "Plugin preset %1 not found" +msgstr "" + +#: gtk_ardour/plugin_ui.cc:903 +msgid "Name for plugin settings:" +msgstr "Ð˜Ð¼Ñ Ð½Ð°Ñтроек модулей:" + +#: gtk_ardour/redirect_automation_line.cc:53 +msgid "redirect automation created for non-plugin" +msgstr "" + +#: gtk_ardour/redirect_automation_time_axis.cc:92 +msgid "add automation event to " +msgstr "" + +#: gtk_ardour/redirect_box.cc:213 +msgid "New send" +msgstr "" + +#: gtk_ardour/redirect_box.cc:214 +#, fuzzy +msgid "Show send controls" +msgstr "иÑпользовать контрольные выходы" + +#: gtk_ardour/redirect_box.cc:360 +msgid "New Plugin ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:361 +#, fuzzy +msgid "New Insert" +msgstr "новый вход" + +#: gtk_ardour/redirect_box.cc:362 +msgid "New Send ..." +msgstr "" + +#: gtk_ardour/redirect_box.cc:380 +#, fuzzy +msgid "Select all" +msgstr "Выделить вÑÑ‘" + +#: gtk_ardour/redirect_box.cc:381 +#, fuzzy +msgid "Deselect all" +msgstr "Выделить вÑÑ‘" + +#: gtk_ardour/redirect_box.cc:389 +#, fuzzy +msgid "Inserts" +msgstr "Ðовый \"возврат\"" + +#: gtk_ardour/redirect_box.cc:390 +#, fuzzy +msgid "Sends" +msgstr "Минуты:Секунды" + +#: gtk_ardour/redirect_box.cc:393 +#, fuzzy +msgid "Select all ..." +msgstr "Выделить вÑÑ‘" + +#: gtk_ardour/redirect_box.cc:406 +#, fuzzy +msgid "Activate All" +msgstr "Ðктивировать" + +#: gtk_ardour/redirect_box.cc:407 +#, fuzzy +msgid "Deactivate All" +msgstr "Деактивировать" + +#: gtk_ardour/redirect_box.cc:488 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point, there are\n" +"%3 active signal streams.\n" +"\n" +"This makes no sense - you are throwing away\n" +"part of the signal." +msgstr "" + +#: gtk_ardour/redirect_box.cc:500 +msgid "" +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point there are\n" +"only %3 active signal streams.\n" +"\n" +"This makes no sense - unless the plugin supports\n" +"side-chain inputs. A future version of Ardour will\n" +"support this type of configuration." +msgstr "" + +#: gtk_ardour/redirect_box.cc:513 +msgid "" +"You attempted to add a plugin (%1).\n" +"\n" +"The I/O configuration doesn't make sense:\n" +"\n" +"The plugin has %2 inputs and %3 outputs.\n" +"The track/bus has %4 inputs and %5 outputs.\n" +"The insertion point, has %6 active signals.\n" +"\n" +"Ardour does not understand what to do in such situations.\n" +msgstr "" + +#: gtk_ardour/redirect_box.cc:616 +msgid "Pre-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:619 +msgid "Post-fader inserts, sends & plugins:" +msgstr "" + +#: gtk_ardour/redirect_box.cc:781 +msgid "" +"You cannot reorder this set of redirects\n" +"in that way because the inputs and\n" +"outputs do not work correctly." +msgstr "" + +#: gtk_ardour/redirect_box.cc:903 +#, fuzzy +msgid "ardour: rename redirect" +msgstr "ardour: переименовать облаÑть" + +#: gtk_ardour/redirect_box.cc:992 gtk_ardour/redirect_box.cc:1043 +msgid "" +"Copying the set of redirects on the clipboard failed,\n" +"probably because the I/O configuration of the plugins\n" +"could not match the configuration of this track." +msgstr "" + +#: gtk_ardour/redirect_box.cc:1064 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this track?\n" +"(this cannot be undone)" +msgstr "" +"Ð’Ñ‹ дейÑтвительно хотите удалить трек \"%1\" ?\n" +"(отмена невозможна)" + +#: gtk_ardour/redirect_box.cc:1067 +#, fuzzy +msgid "" +"Do you really want to remove all redirects from this bus?\n" +"(this cannot be undone)" +msgstr "" +"Ð’Ñ‹ дейÑтвительно хотите удалить трек \"%1\" ?\n" +"(отмена невозможна)" + +#: gtk_ardour/redirect_box.cc:1071 +#, fuzzy +msgid "Yes, remove them all" +msgstr "Да, удалить." + +#: gtk_ardour/redirect_box.cc:1114 +#, fuzzy +msgid "ardour: %1" +msgstr "ardour: " + +#: gtk_ardour/redirect_box.cc:1156 +#, fuzzy +msgid "ardour: %1: %2 (by %3)" +msgstr "ardour: " + +#: gtk_ardour/region_editor.cc:43 +msgid "NAME:" +msgstr "ИМЯ:" + +#: gtk_ardour/region_editor.cc:44 +msgid "lock" +msgstr "фикÑ." + +#: gtk_ardour/region_editor.cc:46 +msgid "opaque" +msgstr "затенить" + +#: gtk_ardour/region_editor.cc:49 +msgid "Layer" +msgstr "Слой" + +#: gtk_ardour/region_editor.cc:57 +msgid "ENVELOPE" +msgstr "ОГИБÐЮЩÐЯ" + +#: gtk_ardour/region_editor.cc:108 +msgid "mute this region" +msgstr "отключить воÑпроизведение Ñтой облаÑти" + +#: gtk_ardour/region_editor.cc:109 +msgid "regions underneath this one cannot be heard" +msgstr "облаÑти ниже Ñтой не могут быть проÑлушаны" + +#: gtk_ardour/region_editor.cc:110 +msgid "prevent any changes to this region" +msgstr "запретить любые Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ñтой облаÑти" + +#: gtk_ardour/region_editor.cc:111 +msgid "use the gain envelope during playback" +msgstr "иÑпользовать огибающую при воÑпроизведении" + +#: gtk_ardour/region_editor.cc:112 +msgid "show the gain envelope" +msgstr "отображать огибающую" + +#: gtk_ardour/region_editor.cc:113 +msgid "use fade in curve during playback" +msgstr "иÑпользовать вводную кривую при воÑпроизведении" + +#: gtk_ardour/region_editor.cc:114 +msgid "use fade out curve during playback" +msgstr "иÑпользовать выводную кривую при воÑпроизведении" + +#: gtk_ardour/region_editor.cc:115 +msgid "audition this region" +msgstr "проÑлушать облаÑть" + +#: gtk_ardour/region_editor.cc:148 +msgid "START:" +msgstr "ÐÐЧÐЛО:" + +#: gtk_ardour/region_editor.cc:150 +msgid "END:" +msgstr "КОÐЕЦ:" + +#: gtk_ardour/region_editor.cc:152 +msgid "LENGTH:" +msgstr "ДЛИÐÐ:" + +#: gtk_ardour/region_editor.cc:177 gtk_ardour/region_editor.cc:198 +#: gtk_ardour/region_editor.cc:234 +msgid "active" +msgstr "активно" + +#: gtk_ardour/region_editor.cc:179 +msgid "visible" +msgstr "отображать" + +#: gtk_ardour/region_editor.cc:197 +msgid "FADE IN" +msgstr "ВВЕДЕÐИЕ Ð’ УРОВЕÐЬ" + +#: gtk_ardour/region_editor.cc:199 gtk_ardour/region_editor.cc:235 +msgid "msecs" +msgstr "мÑек" + +#: gtk_ardour/region_editor.cc:233 +msgid "FADE OUT" +msgstr "СВЕДЕÐИЕ Ð’ ÐОЛЬ" + +#: gtk_ardour/region_editor.cc:276 +msgid "ardour: region " +msgstr "ardour: облаÑть " + +#: gtk_ardour/region_editor.cc:410 +msgid "fade in edit" +msgstr "редактировать введение в уровень" + +#: gtk_ardour/region_editor.cc:422 +msgid "fade out edit" +msgstr "редактировать Ñведение в ноль" + +#: gtk_ardour/regionview.cc:1169 +#, fuzzy +msgid "add gain control point" +msgstr "иÑпользовать контрольные выходы" + +#: gtk_ardour/route_params_ui.cc:58 +msgid "Tracks/Buses" +msgstr "Треки/Шины" + +#: gtk_ardour/route_params_ui.cc:59 +msgid "Pre Redirects" +msgstr "Предобработка" + +#: gtk_ardour/route_params_ui.cc:60 +msgid "Post Redirects" +msgstr "ПоÑтобработка" + +#: gtk_ardour/route_params_ui.cc:105 +#, fuzzy +msgid "Pre-fader Redirects" +msgstr "Предобработка" + +#: gtk_ardour/route_params_ui.cc:106 +#, fuzzy +msgid "Post-fader Redirects" +msgstr "ПоÑтобработка" + +#: gtk_ardour/route_params_ui.cc:138 +#, fuzzy +msgid "ardour: track/bus inspector" +msgstr "ardour: добавить трек/шину" + +#: gtk_ardour/route_params_ui.cc:139 +msgid "ardour_route_parameters" +msgstr "ardour_параметры_маршрутов" + +#: gtk_ardour/route_params_ui.cc:189 +msgid "route display list item for renamed route not found!" +msgstr "" + +#: gtk_ardour/route_params_ui.cc:448 +msgid "NO TRACK" +msgstr "ÐЕТ ТРЕКОВ" + +#: gtk_ardour/route_params_ui.cc:669 +#, fuzzy +msgid "ardour: track/bus inspector: " +msgstr "ardour: добавить трек/шину" + +#: gtk_ardour/route_params_ui.cc:673 +msgid "No Route Selected" +msgstr "Ðет выбранных маршрутов" + +#: gtk_ardour/route_params_ui.cc:674 +#, fuzzy +msgid "ardour: track/bus/inspector: no route selected" +msgstr "ardour: параметры маршрутов: нет выбранных маршрутов" + +#: gtk_ardour/route_ui.cc:134 +msgid "mute change" +msgstr "" + +#: gtk_ardour/route_ui.cc:210 gtk_ardour/route_ui.cc:220 +msgid "solo change" +msgstr "" + +#: gtk_ardour/route_ui.cc:284 +msgid "rec-enable change" +msgstr "" + +#: gtk_ardour/route_ui.cc:423 +#, fuzzy +msgid "Solo-safe" +msgstr "Соло" + +#: gtk_ardour/route_ui.cc:431 gtk_ardour/route_ui.cc:474 +#, fuzzy +msgid "MIDI Bind" +msgstr "MIDI" + +#: gtk_ardour/route_ui.cc:445 +msgid "Pre Fader" +msgstr "Пред фейдер" + +#: gtk_ardour/route_ui.cc:452 +msgid "Post Fader" +msgstr "ПоÑÑ‚ фейдер" + +#: gtk_ardour/route_ui.cc:459 +msgid "Control Outs" +msgstr "Контрольные выходы" + +#: gtk_ardour/route_ui.cc:466 +msgid "Main Outs" +msgstr "Главные выходы" + +#: gtk_ardour/route_ui.cc:503 +msgid "mix group solo change" +msgstr "" + +#: gtk_ardour/route_ui.cc:537 +msgid "mix group mute change" +msgstr "" + +#: gtk_ardour/route_ui.cc:553 +msgid "mix group rec-enable change" +msgstr "" + +#: gtk_ardour/route_ui.cc:576 gtk_ardour/visual_time_axis.cc:258 +msgid "ardour: color selection" +msgstr "ardour: выбор цвета" + +#: gtk_ardour/route_ui.cc:652 +#, fuzzy +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"You may also lose the playlist used by this track.\n" +"(cannot be undone)" +msgstr "" +"Ð’Ñ‹ дейÑтвительно хотите удалить трек \"%1\" ?\n" +"(отмена невозможна)" + +#: gtk_ardour/route_ui.cc:654 +msgid "" +"Do you really want to remove bus \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Ð’Ñ‹ дейÑтвительно хотите удалить шину \"%1\" ?\n" +"(отмена невозможна)" + +#: gtk_ardour/route_ui.cc:657 gtk_ardour/visual_time_axis.cc:299 +msgid "Yes, remove it." +msgstr "Да, удалить." + +#: gtk_ardour/route_ui.cc:691 gtk_ardour/visual_time_axis.cc:358 +msgid "new name: " +msgstr "новое имÑ: " + +#: gtk_ardour/tempo_dialog.cc:14 gtk_ardour/tempo_dialog.cc:31 +msgid "Beats per minute" +msgstr "Ударов в минуту" + +#: gtk_ardour/tempo_dialog.cc:18 gtk_ardour/tempo_dialog.cc:35 +#: gtk_ardour/tempo_dialog.cc:145 gtk_ardour/tempo_dialog.cc:163 +msgid "Beat" +msgstr "ДолÑ" + +#: gtk_ardour/tempo_dialog.cc:140 gtk_ardour/tempo_dialog.cc:158 +msgid "Meter denominator" +msgstr "Знаменатель размера" + +#: gtk_ardour/tempo_dialog.cc:141 gtk_ardour/tempo_dialog.cc:159 +msgid "Beats per bar" +msgstr "Долей на такт" + +#: gtk_ardour/tempo_dialog.cc:178 gtk_ardour/tempo_dialog.cc:189 +msgid "whole (1)" +msgstr "целых (1)" + +#: gtk_ardour/tempo_dialog.cc:179 gtk_ardour/tempo_dialog.cc:191 +msgid "second (2)" +msgstr "половины (2)" + +#: gtk_ardour/tempo_dialog.cc:180 gtk_ardour/tempo_dialog.cc:193 +msgid "third (3)" +msgstr "трети (3)" + +#: gtk_ardour/tempo_dialog.cc:181 gtk_ardour/tempo_dialog.cc:195 +#: gtk_ardour/tempo_dialog.cc:203 +msgid "quarter (4)" +msgstr "четверти (4)" + +#: gtk_ardour/tempo_dialog.cc:182 gtk_ardour/tempo_dialog.cc:197 +msgid "eighth (8)" +msgstr "воÑьмых (8)" + +#: gtk_ardour/tempo_dialog.cc:183 gtk_ardour/tempo_dialog.cc:199 +msgid "sixteenth (16)" +msgstr "шеÑтьнадцатых (16)" + +#: gtk_ardour/tempo_dialog.cc:184 gtk_ardour/tempo_dialog.cc:201 +msgid "thirty-second (32)" +msgstr "тридцать-вторых (32)" + +#: gtk_ardour/tempo_dialog.cc:301 +msgid "garbaged note type entry (%1)" +msgstr "неÑÑное определение ноты (%1)" + +#: gtk_ardour/tempo_dialog.cc:311 +msgid "incomprehensible note type entry (%1)" +msgstr "некорректное определение ноты (%1)" + +#: gtk_ardour/time_axis_view.cc:95 +msgid "gTortnam" +msgstr "" + +#: gtk_ardour/time_axis_view.cc:446 +msgid "Largest" +msgstr "ОгромнаÑ" + +#: gtk_ardour/time_axis_view.cc:447 +msgid "Large" +msgstr "БольшаÑ" + +#: gtk_ardour/time_axis_view.cc:448 +msgid "Larger" +msgstr "Больше" + +#: gtk_ardour/time_axis_view.cc:450 +msgid "Smaller" +msgstr "Меньше" + +#: gtk_ardour/time_axis_view.cc:451 +msgid "Small" +msgstr "МаленькаÑ" + +#: gtk_ardour/time_axis_view.cc:785 +msgid "unknown track height name \"%1\" in XML GUI information" +msgstr "неизвеÑтное Ð¸Ð¼Ñ ÑˆÐ¸Ñ€Ð¸Ð½Ñ‹ трека \"%1\" в XML опиÑании" + +#: gtk_ardour/time_axis_view_item.cc:69 +msgid "TimeAxisViewItemName" +msgstr "" + +#: gtk_ardour/time_axis_view_item.cc:258 +msgid "new duration %1 frames is out of bounds for %2" +msgstr "" + +#: gtk_ardour/time_selection.cc:40 +msgid "programming error: request for non-existent audio range (%1)!" +msgstr "ошибка в программе: request for non-existent audio range (%1)!" + +#: gtk_ardour/utils.cc:57 +msgid "" +"\"\n" +"\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+=" +msgstr "" + +#: gtk_ardour/utils.cc:66 +msgid "aeiou" +msgstr "" + +#: gtk_ardour/utils.cc:75 +msgid "AEIOU" +msgstr "" + +#: gtk_ardour/utils.cc:84 +msgid "bcdfghjklmnpqrtvwxyz" +msgstr "" + +#: gtk_ardour/utils.cc:93 +msgid "BCDFGHJKLMNPQRTVWXYZ" +msgstr "" + +#: gtk_ardour/utils.cc:222 gtk_ardour/utils.cc:265 +msgid "bad XPM header %1" +msgstr "ошибка в XPM заголовке %1" + +#: gtk_ardour/utils.cc:516 +msgid "missing RGBA style for \"%1\"" +msgstr "" + +#: gtk_ardour/visual_time_axis.cc:297 +msgid "" +"Do you really want to remove track \"%1\" ?\n" +"(cannot be undone)" +msgstr "" +"Ð’Ñ‹ дейÑтвительно хотите удалить трек \"%1\" ?\n" +"(отмена невозможна)" + +#: gtk_ardour/visual_time_axis.cc:385 +msgid "A track already exists with that name" +msgstr "Трек Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем уже ÑущеÑтвует" + +#~ msgid "Export to CD" +#~ msgstr "ЭкÑпорт на CD" + +#~ msgid "programming error: location/marker map does not contain location!" +#~ msgstr "ошибка в программе: location/marker map does not contain location!" + +#~ msgid "No toggle button pixmaps found to match toggle-button-[0-9]*.xpm$" +#~ msgstr "Файлы изображений toggle-button-[0-9]*.xpm$ не найдены" + +#~ msgid "" +#~ "No small push button pixmaps found to match small-round-button-[0-9]*.xpm$" +#~ msgstr "Файлы изображений small-round-button-[0-9]*.xpm$ не найдены" + +#~ msgid "No pixmaps found to match hslider[0-9]*.xpm$" +#~ msgstr "Файлы изображений hslider[0-9]*.xpm$ не найдены" + +#~ msgid "No pixmaps found to match vslider[0-9]*.xpm$" +#~ msgstr "Файлы изображений vslider[0-9]*.xpm$ не найдены" + +#~ msgid "Trace MIDI Input" +#~ msgstr "ТраÑÑировка входа MIDI" + +#~ msgid "Trace MIDI Output" +#~ msgstr "ТраÑÑировка выхода MIDI" + +#~ msgid "MTC Port" +#~ msgstr "MTC порт" + +#~ msgid "attempt to timestretch a non-audio track!" +#~ msgstr "попытка применить timestretch-Ñффект к неаудиотреку" + +#~ msgid "cannot create timestretch thread - operation not carried out" +#~ msgstr "cannot create timestretch thread - operation not carried out" + +#~ msgid "ardour: tempo editor" +#~ msgstr "ardour: редактор ритма" + +#~ msgid "ardour_add_track_bus" +#~ msgstr "ardour_add_track_bus" + +#~ msgid "ok" +#~ msgstr "ок" + +#, fuzzy +#~ msgid "apply" +#~ msgstr "авоÑпр" + +#, fuzzy +#~ msgid "fade" +#~ msgstr "Затухание" + +#, fuzzy +#~ msgid "Edit left" +#~ msgstr "Режим редактированиÑ" + +#, fuzzy +#~ msgid "Edit right" +#~ msgstr "Редактировать Ñочетание" + +#, fuzzy +#~ msgid "Edit fade" +#~ msgstr "Режим редактированиÑ" + +#~ msgid "Export region" +#~ msgstr "ЭкÑпорт облаÑти" + +#~ msgid "Region" +#~ msgstr "ОблаÑть" + +#~ msgid "Play selected region" +#~ msgstr "ВоÑпроизвеÑти выделенную облаÑть" + +#~ msgid "clear connections" +#~ msgstr "очиÑтить Ñоед." + +#, fuzzy +#~ msgid "Crossfades in use" +#~ msgstr "КроÑÑфейд" + +#, fuzzy +#~ msgid "outside this computer" +#~ msgstr "Скрыть трек" + +#, fuzzy +#~ msgid "inside this computer" +#~ msgstr "Скрыть трек" diff --git a/gtk2_ardour/point_selection.h b/gtk2_ardour/point_selection.h new file mode 100644 index 0000000000..d0ad08e602 --- /dev/null +++ b/gtk2_ardour/point_selection.h @@ -0,0 +1,12 @@ +#ifndef __ardour_gtk_point_selection_h__ +#define __ardour_gtk_point_selection_h__ + +#include + +#include "automation_selectable.h" + +struct PointSelection : public std::list +{ +}; + +#endif /* __ardour_gtk_point_selection_h__ */ diff --git a/gtk2_ardour/prompter.cc b/gtk2_ardour/prompter.cc new file mode 100644 index 0000000000..7bbb9daea9 --- /dev/null +++ b/gtk2_ardour/prompter.cc @@ -0,0 +1,32 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include "prompter.h" +#include "ardour_ui.h" + +using namespace SigC; + +ArdourPrompter::ArdourPrompter (bool modal) + : Gtkmmext::Prompter (modal) +{ + the_entry().focus_in_event.connect (slot (ARDOUR_UI::generic_focus_in_event)); + the_entry().focus_out_event.connect (slot (ARDOUR_UI::generic_focus_out_event)); +} + diff --git a/gtk2_ardour/prompter.h b/gtk2_ardour/prompter.h new file mode 100644 index 0000000000..c2b78c770a --- /dev/null +++ b/gtk2_ardour/prompter.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_prompter_h__ +#define __ardour_gtk_prompter_h__ + +#include + +class ArdourPrompter : public Gtkmmext::Prompter +{ + public: + ArdourPrompter (bool modal = false); +}; + +#endif /* __ardour_gtk_prompter_h__ */ diff --git a/gtk2_ardour/public_editor.cc b/gtk2_ardour/public_editor.cc new file mode 100644 index 0000000000..f14a216dcc --- /dev/null +++ b/gtk2_ardour/public_editor.cc @@ -0,0 +1,144 @@ +#include "public_editor.h" +#include "editor.h" + +PublicEditor* PublicEditor::_instance = 0; + +PublicEditor::PublicEditor () + : Window (GTK_WINDOW_TOPLEVEL), + KeyboardTarget (*this, "editor") +{ +} + +PublicEditor::~PublicEditor() +{ +} + +gint +PublicEditor::canvas_fade_in_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_fade_in_event (item, event, data); +} +gint +PublicEditor::canvas_fade_in_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_fade_in_handle_event (item, event, data); +} +gint +PublicEditor::canvas_fade_out_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_fade_out_event (item, event, data); +} +gint +PublicEditor::canvas_fade_out_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_fade_out_handle_event (item, event, data); +} +gint +PublicEditor::canvas_crossfade_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_crossfade_view_event (item, event, data); +} +gint +PublicEditor::canvas_region_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_region_view_event (item, event, data); +} +gint +PublicEditor::canvas_region_view_name_highlight_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_region_view_name_highlight_event (item, event, data); +} +gint +PublicEditor::canvas_region_view_name_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_region_view_name_event (item, event, data); +} +gint +PublicEditor::canvas_stream_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_stream_view_event (item, event, data); +} +gint +PublicEditor::canvas_automation_track_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_automation_track_event (item, event, data); +} +gint +PublicEditor::canvas_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_marker_event (item, event, data); +} +gint +PublicEditor::canvas_zoom_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_zoom_rect_event (item, event, data); +} +gint +PublicEditor::canvas_selection_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_selection_rect_event (item, event, data); +} +gint +PublicEditor::canvas_selection_start_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_selection_start_trim_event (item, event, data); +} +gint +PublicEditor::canvas_selection_end_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_selection_end_trim_event (item, event, data); +} +gint +PublicEditor::canvas_control_point_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_control_point_event (item, event, data); +} +gint +PublicEditor::canvas_line_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_line_event (item, event, data); +} +gint +PublicEditor::canvas_tempo_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_tempo_marker_event (item, event, data); +} +gint +PublicEditor::canvas_meter_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_meter_marker_event (item, event, data); +} +gint +PublicEditor::canvas_tempo_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_tempo_bar_event (item, event, data); +} +gint +PublicEditor::canvas_meter_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_meter_bar_event (item, event, data); +} +gint +PublicEditor::canvas_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_marker_bar_event (item, event, data); +} +gint +PublicEditor::canvas_range_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_range_marker_bar_event (item, event, data); +} +gint +PublicEditor::canvas_transport_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_transport_marker_bar_event (item, event, data); +} + +gint +PublicEditor::canvas_imageframe_item_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) { + return instance()->_canvas_imageframe_item_view_event(item, event, data); +} +gint +PublicEditor::canvas_imageframe_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) { + return instance()->_canvas_imageframe_view_event(item, event, data); +} +gint +PublicEditor::canvas_imageframe_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_imageframe_start_handle_event(item, event, data); +} +gint +PublicEditor::canvas_imageframe_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_imageframe_end_handle_event(item, event, data); +} +gint +PublicEditor::canvas_marker_time_axis_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_marker_time_axis_view_event(item, event, data); +} +gint +PublicEditor::canvas_markerview_item_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_markerview_item_view_event(item, event, data); +} +gint +PublicEditor::canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_markerview_start_handle_event(item, event, data); +} +gint +PublicEditor::canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) { + return instance()->_canvas_markerview_end_handle_event(item, event, data); +} diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h new file mode 100644 index 0000000000..e60f14f6b2 --- /dev/null +++ b/gtk2_ardour/public_editor.h @@ -0,0 +1,187 @@ +#ifndef __gtk_ardour_public_editor_h__ +#define __gtk_ardour_public_editor_h__ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "editing.h" +#include "keyboard_target.h" + +namespace ARDOUR { + class Session; + class AudioExportSpecification; + class AudioRegion; + class Playlist; + class RouteGroup; +} + +namespace Gtk { + class Container; + class Menu; +} + +class Editor; +class TimeAxisViewItem; +class TimeAxisView; +class PluginSelector; +class PlaylistSelector; +class XMLNode; +class Selection; + +class PublicEditor : public Gtk::Window, public Stateful, public KeyboardTarget { + public: + PublicEditor(); + virtual ~PublicEditor(); + + typedef list TrackViewList; + + static PublicEditor* instance() { return _instance; } + + virtual void connect_to_session (ARDOUR::Session*) = 0; + virtual ARDOUR::Session* current_session() const = 0; + virtual void set_snap_to (Editing::SnapType) = 0; + virtual void set_snap_mode (Editing::SnapMode) = 0; + virtual void set_snap_threshold (double) = 0; + virtual void undo (uint32_t n = 1) = 0; + virtual void redo (uint32_t n = 1) = 0; + virtual void set_mouse_mode (Editing::MouseMode, bool force = false) = 0; + virtual void step_mouse_mode (bool next) = 0; + virtual Editing::MouseMode current_mouse_mode () = 0; + virtual void add_imageframe_time_axis(std::string track_name, void*) = 0; + virtual void add_imageframe_marker_time_axis(std::string track_name, TimeAxisView* marked_track, void*) = 0; + virtual void connect_to_image_compositor() = 0; + virtual void scroll_timeaxis_to_imageframe_item(const TimeAxisViewItem* item) = 0; + virtual TimeAxisView* get_named_time_axis(std::string name) = 0; + virtual bool consider_auditioning (ARDOUR::AudioRegion*) = 0; + virtual void set_show_waveforms (bool yn) = 0; + virtual bool show_waveforms() const = 0; + virtual void set_show_waveforms_recording (bool yn) = 0; + virtual bool show_waveforms_recording() const = 0; + virtual void new_region_from_selection () = 0; + virtual void separate_region_from_selection () = 0; + virtual void toggle_playback (bool with_abort) = 0; + virtual void set_edit_menu (Gtk::Menu&) = 0; + virtual jack_nframes_t unit_to_frame (double unit) = 0; + virtual double frame_to_unit (jack_nframes_t frame) = 0; + virtual double frame_to_unit (double frame) = 0; + virtual jack_nframes_t pixel_to_frame (double pixel) = 0; + virtual gulong frame_to_pixel (jack_nframes_t frame) = 0; + virtual Selection& get_selection() const = 0; + virtual Selection& get_cut_buffer() const = 0; + virtual void play_selection () = 0; + virtual void set_show_measures (bool yn) = 0; + virtual bool show_measures () const = 0; + virtual void export_session() = 0; + virtual void export_selection() = 0; + virtual void add_toplevel_controls (Gtk::Container&) = 0; + virtual void set_zoom_focus (Editing::ZoomFocus) = 0; + virtual Editing::ZoomFocus get_zoom_focus () const = 0; + virtual gdouble get_current_zoom () = 0; + virtual PlaylistSelector& playlist_selector() const = 0; + virtual void route_name_changed (TimeAxisView *) = 0; + virtual void clear_playlist (ARDOUR::Playlist&) = 0; + virtual void set_selected_mixer_strip (TimeAxisView&) = 0; + virtual void unselect_strip_in_display (TimeAxisView& tv) = 0; + virtual void set_follow_playhead (bool yn) = 0; + virtual void toggle_follow_playhead () = 0; + virtual bool follow_playhead() const = 0; + virtual void toggle_xfade_visibility () = 0; + virtual void set_xfade_visibility (bool yn) = 0; + virtual bool xfade_visibility() const = 0; + virtual void ensure_float (Gtk::Window&) = 0; + virtual void show_window () = 0; + virtual TrackViewList* get_valid_views (TimeAxisView*, ARDOUR::RouteGroup* grp = 0) = 0; + virtual jack_nframes_t leftmost_position() const = 0; + virtual jack_nframes_t current_page_frames() const = 0; + virtual void temporal_zoom_step (bool coarser) = 0; + virtual void scroll_tracks_down_line () = 0; + virtual void scroll_tracks_up_line () = 0; + virtual bool new_regionviews_display_gain () = 0; + virtual void prepare_for_cleanup () = 0; + virtual void reposition_x_origin (jack_nframes_t frame) = 0; + virtual void remove_last_capture () = 0; + + SigC::Signal1 DisplayControlChanged; + SigC::Signal0 ZoomFocusChanged; + SigC::Signal0 ZoomChanged; + SigC::Signal0 XOriginChanged; + SigC::Signal0 Resized; + + static gint canvas_crossfade_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_fade_in_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_fade_in_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_fade_out_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_fade_out_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_region_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_region_view_name_highlight_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_region_view_name_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_stream_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_zoom_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_selection_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_selection_start_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_selection_end_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_control_point_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_line_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_tempo_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_meter_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_tempo_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_meter_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_range_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_transport_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data); + static gint canvas_imageframe_item_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) ; + static gint canvas_imageframe_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) ; + static gint canvas_imageframe_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + static gint canvas_imageframe_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + static gint canvas_marker_time_axis_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + static gint canvas_markerview_item_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + static gint canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + static gint canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + static gint canvas_automation_track_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) ; + + protected: + virtual gint _canvas_fade_in_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_fade_in_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_fade_out_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_fade_out_handle_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_crossfade_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_region_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_region_view_name_highlight_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_region_view_name_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_stream_view_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_zoom_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_selection_rect_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_selection_start_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_selection_end_trim_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_control_point_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_line_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_tempo_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_meter_marker_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_tempo_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_meter_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_range_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_transport_marker_bar_event (GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_imageframe_item_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_imageframe_view_event(GtkCanvasItem *item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_imageframe_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_imageframe_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_marker_time_axis_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_markerview_item_view_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_markerview_start_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_markerview_end_handle_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + virtual gint _canvas_automation_track_event(GtkCanvasItem* item, GdkEvent* event, gpointer data) = 0; + + static PublicEditor* _instance; +}; + +#endif // __gtk_ardour_public_editor_h__ diff --git a/gtk2_ardour/redirect_automation_line.cc b/gtk2_ardour/redirect_automation_line.cc new file mode 100644 index 0000000000..138d376a65 --- /dev/null +++ b/gtk2_ardour/redirect_automation_line.cc @@ -0,0 +1,95 @@ +/* + Copyright (C) 2002-2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include "public_editor.h" +#include "redirect_automation_line.h" +#include "audio_time_axis.h" +#include "utils.h" + +#include +#include +#include +#include + +#include "i18n.h" + +using namespace std; +using namespace ARDOUR; + +RedirectAutomationLine::RedirectAutomationLine (string name, Redirect& rd, uint32_t port, Session& s, + TimeAxisView& tv, GtkCanvasItem* parent, + AutomationList& l, + gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer), + gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer)) + + : AutomationLine (name, tv, parent, l, point_callback, line_callback), + session (s), + _redirect (rd), + _port (port) +{ + set_verbose_cursor_uses_gain_mapping (false); + + PluginInsert *pi; + Plugin::ParameterDescriptor desc; + + if ((pi = dynamic_cast(&_redirect)) == 0) { + fatal << _("redirect automation created for non-plugin") << endmsg; + /*NOTREACHED*/ + } + + pi->plugin().get_parameter_descriptor (_port, desc); + + upper = desc.upper; + lower = desc.lower; + + if (desc.toggled) { + no_draw = true; + return; + } + + no_draw = false; + range = upper - lower; + + /* XXX set min/max for underlying curve ??? */ +} + +string +RedirectAutomationLine::get_verbose_cursor_string (float fraction) +{ + char buf[32]; + + snprintf (buf, sizeof (buf), "%.2f", lower + (fraction * range)); + return buf; +} + +void +RedirectAutomationLine::view_to_model_y (double& y) +{ + y = lower + (y * range); +} + +void +RedirectAutomationLine::model_to_view_y (double& y) +{ + y = (y - lower) / range; + y = max (0.0, y); + y = min (y, 1.0); +} + diff --git a/gtk2_ardour/redirect_automation_line.h b/gtk2_ardour/redirect_automation_line.h new file mode 100644 index 0000000000..1d5971fe58 --- /dev/null +++ b/gtk2_ardour/redirect_automation_line.h @@ -0,0 +1,64 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_redirect_automation_line_h__ +#define __ardour_gtk_redirect_automation_line_h__ + +#include +#include +#include + +#include "automation_line.h" + +namespace ARDOUR { + class Session; + class Redirect; +} + +class TimeAxisView; + +class RedirectAutomationLine : public AutomationLine +{ + public: + RedirectAutomationLine (string name, ARDOUR::Redirect&, uint32_t port, ARDOUR::Session&, TimeAxisView&, GtkCanvasItem* parent, + ARDOUR::AutomationList&, + gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer), + gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer)); + + uint32_t port() const { return _port; } + ARDOUR::Redirect& redirect() const { return _redirect; } + + string get_verbose_cursor_string (float); + + private: + ARDOUR::Session& session; + ARDOUR::Redirect& _redirect; + uint32_t _port; + float upper; + float lower; + float range; + + void view_to_model_y (double&); + void model_to_view_y (double&); + void change_model (uint32_t, double x, double y); + void change_model_range (uint32_t, uint32_t, double delta); +}; + +#endif /* __ardour_gtk_region_gain_line_h__ */ diff --git a/gtk2_ardour/redirect_automation_time_axis.cc b/gtk2_ardour/redirect_automation_time_axis.cc new file mode 100644 index 0000000000..5bbd7e290f --- /dev/null +++ b/gtk2_ardour/redirect_automation_time_axis.cc @@ -0,0 +1,169 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include "redirect_automation_time_axis.h" +#include "automation_line.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; + +RedirectAutomationTimeAxisView::RedirectAutomationTimeAxisView (Session& s, Route& r, PublicEditor& e, TimeAxisView& parent, Widget* p, std::string n, + uint32_t prt, Redirect& rd, string state_name) + + : AxisView (s), + AutomationTimeAxisView (s, r, e, parent, p, n, state_name, rd.name()), + redirect (rd), + port (prt) + +{ + char buf[32]; + xml_node = 0; + _marked_for_display = false; + + ensure_xml_node (); + + XMLNodeList kids; + XMLNodeConstIterator iter; + + kids = xml_node->children (); + + snprintf (buf, sizeof(buf), "Port_%" PRIu32, port); + + for (iter = kids.begin(); iter != kids.end(); ++iter) { + if ((*iter)->name() == buf) { + + XMLProperty *shown = (*iter)->property("shown_editor"); + + if (shown && shown->value() == "yes") { + _marked_for_display = true; + } + break; + } + } +} + +RedirectAutomationTimeAxisView::~RedirectAutomationTimeAxisView () +{ +} + +void +RedirectAutomationTimeAxisView::add_automation_event (GtkCanvasItem* item, GdkEvent* event, jack_nframes_t when, double y) +{ + double x = 0; + + gtk_canvas_item_w2i (canvas_display, &x, &y); + + /* compute vertical fractional position */ + + if (y < 0) + y = 0; + else if (y > height) + y = height; + + y = 1.0 - (y / height); + + /* map to model space */ + + if (!lines.empty()) { + AutomationList& alist (redirect.automation_list(port)); + string description = _("add automation event to "); + description += redirect.describe_parameter (port); + + lines.front()->view_to_model_y (y); + + _session.begin_reversible_command (description); + _session.add_undo (alist.get_memento()); + alist.add (when, y); + _session.add_redo_no_execute (alist.get_memento()); + _session.commit_reversible_command (); + _session.set_dirty (); + } +} + +void +RedirectAutomationTimeAxisView::ensure_xml_node () +{ + if (xml_node == 0) { + if ((xml_node = redirect.extra_xml ("GUI")) == 0) { + xml_node = new XMLNode ("GUI"); + redirect.add_extra_xml (*xml_node); + } + } +} + +guint32 +RedirectAutomationTimeAxisView::show_at (double y, int& nth, Gtk::VBox *parent) +{ + ensure_xml_node (); + update_extra_xml_shown (true); + + return TimeAxisView::show_at (y, nth, parent); +} + +void +RedirectAutomationTimeAxisView::hide () +{ + ensure_xml_node (); + update_extra_xml_shown (false); + + TimeAxisView::hide (); +} + + +void +RedirectAutomationTimeAxisView::update_extra_xml_shown (bool editor_shown) +{ + char buf[32]; + + XMLNodeList nlist = xml_node->children (); + XMLNodeConstIterator i; + XMLNode * port_node = 0; + + snprintf (buf, sizeof(buf), "Port_%" PRIu32, port); + + for (i = nlist.begin(); i != nlist.end(); ++i) { + if ((*i)->name() == buf) { + port_node = (*i); + break; + } + } + + if (!port_node) { + port_node = new XMLNode(buf); + xml_node->add_child_nocopy(*port_node); + } + + port_node->add_property ("shown_editor", editor_shown ? "yes": "no"); + +} + +void +RedirectAutomationTimeAxisView::set_automation_state (AutoState state) +{ + if (!ignore_state_request) { + redirect.automation_list (port).set_automation_state (state); + } +} diff --git a/gtk2_ardour/redirect_automation_time_axis.h b/gtk2_ardour/redirect_automation_time_axis.h new file mode 100644 index 0000000000..d4e7a46e71 --- /dev/null +++ b/gtk2_ardour/redirect_automation_time_axis.h @@ -0,0 +1,43 @@ +#ifndef __ardour_gtk_redirect_automation_time_axis_h__ +#define __ardour_gtk_redirect_automation_time_axis_h__ + +#include +#include "automation_time_axis.h" + +namespace ARDOUR { + class Redirect; +} + +class RedirectAutomationTimeAxisView : public AutomationTimeAxisView +{ + public: + RedirectAutomationTimeAxisView (ARDOUR::Session&, + ARDOUR::Route&, + PublicEditor&, + TimeAxisView& parent, + Gtk::Widget* parent, + std::string name, + uint32_t port, + ARDOUR::Redirect& rd, + std::string state_name); + + ~RedirectAutomationTimeAxisView(); + + void add_automation_event (GtkCanvasItem *item, GdkEvent *event, jack_nframes_t, double); + + guint32 show_at (double y, int& nth, Gtk::VBox *parent); + void hide (); + + + private: + ARDOUR::Redirect& redirect; + uint32_t port; + + XMLNode *xml_node; + void ensure_xml_node(); + void update_extra_xml_shown (bool editor_shown); + + void set_automation_state (ARDOUR::AutoState); +}; + +#endif /* __ardour_gtk_redirect_automation_time_axis_h__ */ diff --git a/gtk2_ardour/redirect_box.cc b/gtk2_ardour/redirect_box.cc new file mode 100644 index 0000000000..66fc0cb347 --- /dev/null +++ b/gtk2_ardour/redirect_box.cc @@ -0,0 +1,1203 @@ +/* + Copyright (C) 2000-2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ardour_ui.h" +#include "ardour_dialog.h" +#include "ardour_message.h" +#include "public_editor.h" +#include "redirect_box.h" +#include "keyboard.h" +#include "plugin_selector.h" +#include "route_redirect_selection.h" +#include "mixer_ui.h" + +#include "plugin_ui.h" +#include "send_ui.h" +#include "io_selector.h" +#include "utils.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace SigC; +using namespace ARDOUR; +using namespace Gtk; +using namespace Gtkmmext; + + + +RedirectBox::RedirectBox (Placement pcmnt, Session& sess, Route& rt, PluginSelector &plugsel, RouteRedirectSelection & rsel, bool owner_is_mixer) + : _route(rt), + _session(sess), + _owner_is_mixer (owner_is_mixer), + _placement(pcmnt), + _plugin_selector(plugsel), + _rr_selection(rsel), + redirect_display (1) +{ + _width = Wide; + redirect_menu = 0; + send_action_menu = 0; + redirect_drag_in_progress = false; + + redirect_display.set_name ("MixerRedirectSelector"); + redirect_display.column_titles_active (); + redirect_display.set_reorderable (true); + redirect_display.set_button_actions (0, (GTK_BUTTON_SELECTS|GTK_BUTTON_DRAGS)); + redirect_display.set_button_actions (1, 0); + redirect_display.set_button_actions (2, 0); + redirect_display.set_button_actions (3, 0); + redirect_display.drag_begin.connect (slot (*this, &RedirectBox::redirect_drag_begin)); + redirect_display.drag_end.connect (slot (*this, &RedirectBox::redirect_drag_end)); + redirect_display.set_usize (-1, 48); + redirect_display.set_selection_mode (GTK_SELECTION_MULTIPLE); + redirect_display.set_shadow_type (GTK_SHADOW_IN); + redirect_display.row_move.connect (slot (*this, &RedirectBox::redirects_reordered)); + + redirect_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + redirect_scroller.add (redirect_display); + redirect_eventbox.add (redirect_scroller); + pack_start (redirect_eventbox, true, true); + + redirect_scroller.show (); + redirect_display.show (); + redirect_eventbox.show (); + show_all (); + + _route.redirects_changed.connect (slot (*this, &RedirectBox::redirects_changed)); + + redirect_display.button_press_event.connect (slot (*this, &RedirectBox::redirect_button)); + redirect_display.button_release_event.connect (slot (*this, &RedirectBox::redirect_button)); + + redirect_display.button_release_event.connect_after (slot (do_not_propagate)); + _plugin_selector.hide.connect(slot(*this,&RedirectBox::disconnect_newplug)); + + redirect_display.click_column.connect (slot (*this, &RedirectBox::show_redirect_menu)); + + set_stuff_from_route (); + + /* start off as a passthru strip. we'll correct this, if necessary, + in update_diskstream_display(). + */ + + //set_name ("AudioTrackStripBase"); + + /* now force an update of all the various elements */ + + redirects_changed (0); + + //add_events (GDK_BUTTON_RELEASE_MASK); +} + +RedirectBox::~RedirectBox () +{ +// GoingAway(); /* EMIT_SIGNAL */ + +} + +void +RedirectBox::set_stuff_from_route () +{ +} + +void +RedirectBox::set_title (const std::string & title) +{ + redirect_display.column(0).set_title (title); +} + +void +RedirectBox::set_title_shown (bool flag) +{ + if (flag) { + redirect_display.column_titles_show(); + } else { + redirect_display.column_titles_hide(); + } +} + + +void +RedirectBox::update() +{ + redirects_changed(0); +} + + +void +RedirectBox::set_width (Width w) +{ + if (_width == w) { + return; + } + _width = w; + + redirects_changed(0); +} + + +void +RedirectBox::remove_redirect_gui (Redirect *redirect) +{ + Insert *insert = 0; + Send *send = 0; + PortInsert *port_insert = 0; + + if ((insert = dynamic_cast (redirect)) != 0) { + + if ((port_insert = dynamic_cast (insert)) != 0) { + PortInsertUI *io_selector = reinterpret_cast (port_insert->get_gui()); + port_insert->set_gui (0); + delete io_selector; + } + + } else if ((send = dynamic_cast (insert)) != 0) { + SendUIWindow *sui = reinterpret_cast (send->get_gui()); + send->set_gui (0); + delete sui; + } +} + +void +RedirectBox::build_send_action_menu () + +{ + using namespace Menu_Helpers; + + send_action_menu = new Menu; + send_action_menu->set_name ("ArdourContextMenu"); + MenuList& items = send_action_menu->items(); + + items.push_back (MenuElem (_("New send"), slot (*this, &RedirectBox::new_send))); + items.push_back (MenuElem (_("Show send controls"), slot (*this, &RedirectBox::show_send_controls))); +} + +void +RedirectBox::show_send_controls () + +{ +} + +void +RedirectBox::new_send () + +{ +} + +void +RedirectBox::show_redirect_menu (gint arg) +{ + if (redirect_menu == 0) { + redirect_menu = build_redirect_menu (redirect_display); + } + + redirect_menu->popup (1, 0); +} + +void +RedirectBox::redirect_drag_begin (GdkDragContext *context) +{ + redirect_drag_in_progress = true; +} + +void +RedirectBox::redirect_drag_end (GdkDragContext *context) +{ + redirect_drag_in_progress = false; +} + +gint +RedirectBox::redirect_button (GdkEventButton *ev) +{ + gint row=-1, col=-1; + Redirect *redirect; + CList *clist = &redirect_display; + + if (clist->get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 1) { + redirect = 0; + } else { + redirect = reinterpret_cast (clist->row (row).get_data ()); + } + + switch (ev->type) { + case GDK_BUTTON_PRESS: + return FALSE; + + case GDK_2BUTTON_PRESS: + if (ev->state != 0) { + return FALSE; + } + /* might be edit event, see below */ + break; + + case GDK_BUTTON_RELEASE: + if (redirect_drag_in_progress) { + // drag-n-drop reordering + return stop_signal (*clist, "button-release-event"); + } + /* continue on */ + break; + + default: + /* shouldn't be here, but gcc complains */ + return FALSE; + } + + if (redirect && Keyboard::is_delete_event (ev)) { + + Gtk::Main::idle.connect (bind (slot (*this, &RedirectBox::idle_delete_redirect), redirect)); + return TRUE; + + } else if (redirect && (Keyboard::is_edit_event (ev) || ev->type == GDK_2BUTTON_PRESS)) { + + if (_session.engine().connected()) { + /* XXX giving an error message here is hard, because we may be in the midst of a button press */ + edit_redirect (redirect); + } + return TRUE; + + } else if (Keyboard::is_context_menu_event (ev)) { + show_redirect_menu(0); + return stop_signal (*clist, "button-release-event"); + + } else { + switch (ev->button) { + case 1: + if (redirect) { + using namespace CList_Helpers; + SelectionList& sel (redirect_display.selection()); + bool selecting = true; + + for (SelectionIterator i = sel.begin(); i != sel.end(); ++i) { + if ((*i).get_row_num() == row) { + // clicked row is not selected yet, so it is + // becoming selected now + selecting = false; + break; + } + } + + if (selecting) { + RedirectSelected (redirect); // emit + } + else { + RedirectUnselected (redirect); // emit + } + } + return FALSE; + break; + + case 2: + if (redirect) { + redirect->set_active (!redirect->active(), this); + } + break; + + case 3: + break; + + default: + return FALSE; + } + } + + return TRUE; +} + +Menu * +RedirectBox::build_redirect_menu (CList& clist) +{ + using namespace Menu_Helpers; + Menu * menu = new Menu; + menu->set_name ("ArdourContextMenu"); + MenuList& items = menu->items(); + menu->set_name ("ArdourContextMenu"); + + /* new stuff */ + + items.push_back (MenuElem (_("New Plugin ..."), slot (*this, &RedirectBox::choose_plugin))); + items.push_back (MenuElem (_("New Insert"), slot (*this, &RedirectBox::choose_insert))); + items.push_back (MenuElem (_("New Send ..."), slot (*this, &RedirectBox::choose_send))); + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Clear"), slot (*this, &RedirectBox::clear_redirects))); + items.push_back (SeparatorElem()); + + /* standard editing stuff */ + + items.push_back (MenuElem (_("Cut"), slot (*this, &RedirectBox::cut_redirects))); + selection_dependent_items.push_back (items.back()); + items.push_back (MenuElem (_("Copy"), slot (*this, &RedirectBox::copy_redirects))); + selection_dependent_items.push_back (items.back()); + items.push_back (MenuElem (_("Paste"), slot (*this, &RedirectBox::paste_redirects))); + redirect_paste_item = items.back(); + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Rename"), slot (*this, &RedirectBox::rename_redirects))); + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Select all"), slot (*this, &RedirectBox::select_all_redirects))); + items.push_back (MenuElem (_("Deselect all"), slot (*this, &RedirectBox::deselect_all_redirects))); + +#if LATER + Menu *select_sub_menu = manage (new Menu); + MenuList& sitems = select_sub_menu->items(); + select_sub_menu->set_name ("ArdourContextMenu"); + + sitems.push_back (MenuElem (_("Plugins"))); + sitems.push_back (MenuElem (_("Inserts"))); + sitems.push_back (MenuElem (_("Sends"))); + sitems.push_back (SeparatorElem()); + + items.push_back (MenuElem (_("Select all ..."), *select_sub_menu)); +#endif + /* activation */ + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Activate"), bind (slot (*this, &RedirectBox::for_selected_redirects), + &RedirectBox::activate_redirect))); + selection_dependent_items.push_back (items.back()); + items.push_back (MenuElem (_("Deactivate"), bind (slot (*this, &RedirectBox::for_selected_redirects), + &RedirectBox::deactivate_redirect))); + selection_dependent_items.push_back (items.back()); + items.push_back (SeparatorElem()); + + items.push_back (MenuElem (_("Activate All"), bind (slot (*this, &RedirectBox::all_redirects_active), true))); + items.push_back (MenuElem (_("Deactivate All"), bind (slot (*this, &RedirectBox::all_redirects_active), false))); + + /* show editors */ + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("Edit"), bind (slot (*this, &RedirectBox::for_selected_redirects), + &RedirectBox::edit_redirect))); + selection_dependent_items.push_back (items.back()); + + menu->map_event.connect (slot (*this, &RedirectBox::redirect_menu_map_handler)); + + return menu; +} + +gint +RedirectBox::redirect_menu_map_handler (GdkEventAny *ev) +{ + using namespace Menu_Helpers; + using namespace CList_Helpers; + + Gtk::CList* clist = &redirect_display; + + bool sensitive = !clist->selection().empty(); + + for (vector::iterator i = selection_dependent_items.begin(); i != selection_dependent_items.end(); ++i) { + (*i)->set_sensitive (sensitive); + } + + redirect_paste_item->set_sensitive (!_rr_selection.redirects.empty()); + return FALSE; +} + +void +RedirectBox::select_all_redirects () +{ + redirect_display.selection().all(); +} + +void +RedirectBox::deselect_all_redirects () +{ + redirect_display.selection().clear (); +} + +void +RedirectBox::choose_plugin () +{ + show_plugin_selector(); +} + +void +RedirectBox::insert_plugin_chosen (Plugin *plugin) +{ + if (plugin) { + + Redirect *redirect = new PluginInsert (_session, *plugin, _placement); + + redirect->active_changed.connect (slot (*this, &RedirectBox::show_redirect_active)); + + uint32_t err_streams; + + if (_route.add_redirect (redirect, this, &err_streams)) { + wierd_plugin_dialog (*plugin, err_streams, _route); + delete redirect; + } + } +} + +void +RedirectBox::wierd_plugin_dialog (Plugin& p, uint32_t streams, IO& io) +{ + ArdourDialog dialog ("wierd plugin dialog"); + Label label; + Button button (_("OK")); + VBox vpacker; + HBox button_box; + + /* i hate this kind of code */ + + if (streams > p.get_info().n_inputs) { + label.set_text (compose (_( +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point, there are\n" +"%3 active signal streams.\n" +"\n" +"This makes no sense - you are throwing away\n" +"part of the signal."), + p.name(), + p.get_info().n_inputs, + streams)); + } else if (streams < p.get_info().n_inputs) { + label.set_text (compose (_( +"You attempted to add a plugin (%1).\n" +"The plugin has %2 inputs\n" +"but at the insertion point there are\n" +"only %3 active signal streams.\n" +"\n" +"This makes no sense - unless the plugin supports\n" +"side-chain inputs. A future version of Ardour will\n" +"support this type of configuration."), + p.name(), + p.get_info().n_inputs, + streams)); + } else { + label.set_text (compose (_( +"You attempted to add a plugin (%1).\n" +"\n" +"The I/O configuration doesn't make sense:\n" +"\n" +"The plugin has %2 inputs and %3 outputs.\n" +"The track/bus has %4 inputs and %5 outputs.\n" +"The insertion point, has %6 active signals.\n" +"\n" +"Ardour does not understand what to do in such situations.\n"), + p.name(), + p.get_info().n_inputs, + p.get_info().n_outputs, + io.n_inputs(), + io.n_outputs(), + streams)); + } + + button_box.pack_start (button, false, true); + + vpacker.set_spacing (12); + vpacker.set_border_width (12); + vpacker.pack_start (label); + vpacker.pack_start (button_box); + + button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 0)); + + dialog.add (vpacker); + dialog.set_name (X_("PluginIODialog")); + dialog.set_position (GTK_WIN_POS_MOUSE); + dialog.set_modal (true); + dialog.show_all (); + + dialog.realize(); + dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + + dialog.run (); +} + +void +RedirectBox::choose_insert () +{ + Redirect *redirect = new PortInsert (_session, _placement); + redirect->active_changed.connect (slot (*this, &RedirectBox::show_redirect_active)); + _route.add_redirect (redirect, this); +} + +void +RedirectBox::choose_send () +{ + Send *send = new Send (_session, _placement); + + /* XXX need redirect lock on route */ + + send->ensure_io (0, _route.max_redirect_outs(), false, this); + + IOSelectorWindow *ios = new IOSelectorWindow (_session, *send, false, true); + + ios->show_all (); + ios->selector().Finished.connect (bind (slot (*this, &RedirectBox::send_io_finished), static_cast(send), ios)); +} + +void +RedirectBox::send_io_finished (IOSelector::Result r, Redirect* redirect, IOSelectorWindow* ios) +{ + switch (r) { + case IOSelector::Cancelled: + delete redirect; + break; + + case IOSelector::Accepted: + _route.add_redirect (redirect, this); + break; + } + + delete_when_idle (ios); +} + +void +RedirectBox::disconnect_newplug () +{ + newplug_connection.disconnect(); +} +void +RedirectBox::show_plugin_selector () +{ + newplug_connection = _plugin_selector.PluginCreated.connect (slot (*this,&RedirectBox::insert_plugin_chosen)); + _plugin_selector.show_all (); +} + +void +RedirectBox::redirects_changed (void *src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RedirectBox::redirects_changed), src)); + + redirect_display.freeze (); + redirect_display.clear (); + redirect_active_connections.clear (); + redirect_name_connections.clear (); + + _route.foreach_redirect (this, &RedirectBox::add_redirect_to_display); + + switch (_placement) { + case PreFader: + build_redirect_tooltip(redirect_display, redirect_eventbox, _("Pre-fader inserts, sends & plugins:")); + break; + case PostFader: + build_redirect_tooltip(redirect_display, redirect_eventbox, _("Post-fader inserts, sends & plugins:")); + break; + } + redirect_display.thaw (); +} + +void +RedirectBox::add_redirect_to_display (Redirect *redirect) +{ + const gchar *rowdata[1]; + gint row; + CList *clist = 0; + + if (redirect->placement() != _placement) { + return; + } + + clist = &redirect_display; + + string rname = redirect_name (*redirect); + rowdata[0] = rname.c_str(); + clist->rows().push_back (rowdata); + row = clist->rows().size() - 1; + clist->row (row).set_data (redirect); + + show_redirect_active (redirect, this); + + redirect_active_connections.push_back + (redirect->active_changed.connect (slot (*this, &RedirectBox::show_redirect_active))); + redirect_name_connections.push_back + (redirect->name_changed.connect (bind (slot (*this, &RedirectBox::show_redirect_name), redirect))); +} + +string +RedirectBox::redirect_name (Redirect& redirect) +{ + Send *send; + string name_display; + + if (!redirect.active()) { + name_display = " ("; + } + + if ((send = dynamic_cast (&redirect)) != 0) { + + name_display += '>'; + + /* grab the send name out of its overall name */ + + string::size_type lbracket, rbracket; + lbracket = send->name().find ('['); + rbracket = send->name().find (']'); + + switch (_width) { + case Wide: + name_display += send->name().substr (lbracket+1, lbracket-rbracket-1); + break; + case Narrow: + name_display += short_version (send->name().substr (lbracket+1, lbracket-rbracket-1), 4); + break; + } + + } else { + + switch (_width) { + case Wide: + name_display += redirect.name(); + break; + case Narrow: + name_display += short_version (redirect.name(), 5); + break; + } + + } + + if (!redirect.active()) { + name_display += ')'; + } + + return name_display; +} + +void +RedirectBox::build_redirect_tooltip (CList& clist, EventBox& box, string start) +{ + CList_Helpers::RowIterator ri; + string tip(start); + + for (ri = clist.rows().begin(); ri != clist.rows().end(); ++ri) { + tip += '\n'; + tip += clist.cell(ri->get_row_num(), 0).get_text(); + } + ARDOUR_UI::instance()->tooltips().set_tip (box, tip); +} + +void +RedirectBox::show_redirect_name (void* src, Redirect *redirect) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RedirectBox::show_redirect_name), src, redirect)); + + show_redirect_active (redirect, src); +} + +void +RedirectBox::show_redirect_active (Redirect *redirect, void *src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RedirectBox::show_redirect_active), redirect, src)); + + CList_Helpers::RowIterator ri; + CList *clist; + + if ((ri = redirect_display.rows().find_data (redirect)) == redirect_display.rows().end()) { + return; + } + + clist = &redirect_display; + + clist->cell(ri->get_row_num(), 0).set_text (redirect_name (*redirect)); + + if (redirect->active()) { + // ri->select (); + } else { + // ri->unselect (); + } +} + +void +RedirectBox::redirects_reordered (gint src, gint dst) +{ + /* this is called before the reorder has been done, so just queue + something for idle time. + */ + + Gtk::Main::idle.connect (slot (*this, &RedirectBox::compute_redirect_sort_keys)); +} + +gint +RedirectBox::compute_redirect_sort_keys () +{ + CList_Helpers::RowList::iterator i; + uint32_t sort_key; + + sort_key = 0; + + for (i = redirect_display.rows().begin(); i != redirect_display.rows().end(); ++i) { + Redirect *redirect = reinterpret_cast (i->get_data()); + redirect->set_sort_key (sort_key, this); + sort_key++; + } + + if (_route.sort_redirects ()) { + + redirects_changed (0); + + /* now tell them about the problem */ + + ArdourDialog dialog ("wierd plugin dialog"); + Label label; + Button button (_("OK")); + VBox vpacker; + HBox button_box; + + label.set_text (_("\ +You cannot reorder this set of redirects\n\ +in that way because the inputs and\n\ +outputs do not work correctly.")); + + button_box.pack_start (button, false, true); + + vpacker.set_spacing (12); + vpacker.set_border_width (12); + vpacker.pack_start (label); + vpacker.pack_start (button_box); + + button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 0)); + + dialog.add (vpacker); + dialog.set_name (X_("PluginIODialog")); + dialog.set_position (GTK_WIN_POS_MOUSE); + dialog.set_modal (true); + dialog.show_all (); + + dialog.realize(); + dialog.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH)); + + dialog.run (); + } + + return FALSE; +} + +void +RedirectBox::rename_redirects () +{ + vector to_be_renamed; + + get_selected_redirects (to_be_renamed); + + if (to_be_renamed.empty()) { + return; + } + + for (vector::iterator i = to_be_renamed.begin(); i != to_be_renamed.end(); ++i) { + rename_redirect (*i); + } +} + +void +RedirectBox::cut_redirects () +{ + vector to_be_removed; + + get_selected_redirects (to_be_removed); + + if (to_be_removed.empty()) { + return; + } + + /* this essentially transfers ownership of the redirect + of the redirect from the route to the mixer + selection. + */ + + _rr_selection.set (to_be_removed); + + for (vector::iterator i = to_be_removed.begin(); i != to_be_removed.end(); ++i) { + + void* gui = (*i)->get_gui (); + + if (gui) { + static_cast(gui)->hide (); + } + + if (_route.remove_redirect (*i, this)) { + /* removal failed */ + _rr_selection.remove (*i); + } + + } +} + +void +RedirectBox::copy_redirects () +{ + vector to_be_copied; + vector copies; + + get_selected_redirects (to_be_copied); + + if (to_be_copied.empty()) { + return; + } + + for (vector::iterator i = to_be_copied.begin(); i != to_be_copied.end(); ++i) { + copies.push_back (Redirect::clone (**i)); + } + + _rr_selection.set (copies); +} + +gint +RedirectBox::idle_delete_redirect (Redirect *redirect) +{ + /* NOT copied to _mixer.selection() */ + + if (_route.remove_redirect (redirect, this)) { + /* removal failed */ + return FALSE; + } + + delete redirect; + return FALSE; +} + +void +RedirectBox::rename_redirect (Redirect* redirect) +{ + ArdourDialog dialog ("rename redirect dialog"); + Entry entry; + VBox vbox; + HBox hbox; + Button ok_button (_("OK")); + Button cancel_button (_("Cancel")); + + dialog.set_title (_("ardour: rename redirect")); + dialog.set_name ("RedirectRenameWindow"); + dialog.set_usize (300, -1); + dialog.set_position (GTK_WIN_POS_MOUSE); + dialog.set_modal (true); + + vbox.set_border_width (12); + vbox.set_spacing (12); + vbox.pack_start (entry, false, false); + vbox.pack_start (hbox, false, false); + hbox.pack_start (ok_button); + hbox.pack_start (cancel_button); + + dialog.add (vbox); + + entry.set_name ("RedirectNameDisplay"); + entry.set_text (redirect->name()); + entry.select_region (0, -1); + entry.grab_focus (); + + ok_button.set_name ("EditorGTKButton"); + cancel_button.set_name ("EditorGTKButton"); + + entry.activate.connect (bind (slot (dialog, &ArdourDialog::stop), 1)); + cancel_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), -1)); + ok_button.clicked.connect (bind (slot (dialog, &ArdourDialog::stop), 1)); + + /* recurse */ + + dialog.set_keyboard_input (true); + dialog.run (); + + if (dialog.run_status() == 1) { + redirect->set_name (entry.get_text(), this); + } +} + +void +RedirectBox::cut_redirect (Redirect *redirect) +{ + /* this essentially transfers ownership of the redirect + of the redirect from the route to the mixer + selection. + */ + + _rr_selection.add (redirect); + + void* gui = redirect->get_gui (); + + if (gui) { + static_cast(gui)->hide (); + } + + if (_route.remove_redirect (redirect, this)) { + _rr_selection.remove (redirect); + } +} + +void +RedirectBox::copy_redirect (Redirect *redirect) +{ + Redirect* copy = Redirect::clone (*redirect); + _rr_selection.add (copy); +} + +void +RedirectBox::paste_redirects () +{ + if (_rr_selection.redirects.empty()) { + return; + } + + RedirectSelection& sel (_rr_selection.redirects); + list others; + + for (list::iterator i = sel.begin(); i != sel.end(); ++i) { + + Redirect* copy = Redirect::clone (**i); + + copy->set_placement (_placement, this); + others.push_back (copy); + } + + if (_route.add_redirects (others, this)) { + for (list::iterator i = others.begin(); i != others.end(); ++i) { + delete *i; + } + + string msg = _( + "Copying the set of redirects on the clipboard failed,\n\ +probably because the I/O configuration of the plugins\n\ +could not match the configuration of this track."); + ArdourMessage am (0, X_("bad redirect copy dialog"), msg); + } +} + +void +RedirectBox::activate_redirect (Redirect *r) +{ + r->set_active (true, 0); +} + +void +RedirectBox::deactivate_redirect (Redirect *r) +{ + r->set_active (false, 0); +} + +void +RedirectBox::get_selected_redirects (vector& redirects) +{ + using namespace CList_Helpers; + SelectionList& sel (redirect_display.selection()); + + for (SelectionIterator i = sel.begin(); i != sel.end(); ++i) { + Redirect* redirect = reinterpret_cast ((*i).get_data ()); + redirects.push_back (redirect); + } +} + +void +RedirectBox::for_selected_redirects (void (RedirectBox::*pmf)(Redirect*)) +{ + using namespace CList_Helpers; + SelectionList& sel (redirect_display.selection()); + + for (SelectionIterator i = sel.begin(); i != sel.end(); ++i) { + Redirect* redirect = reinterpret_cast ((*i).get_data ()); + (this->*pmf)(redirect); + } +} + +void +RedirectBox::clone_redirects () +{ + RouteSelection& routes (_rr_selection.routes); + + if (!routes.empty()) { + if (_route.copy_redirects (*routes.front(), _placement)) { + string msg = _( +"Copying the set of redirects on the clipboard failed,\n\ +probably because the I/O configuration of the plugins\n\ +could not match the configuration of this track."); + ArdourMessage am (0, X_("bad redirect copy dialog"), msg); + } + } +} + +void +RedirectBox::all_redirects_active (bool state) +{ + _route.all_redirects_active (state); +} + +void +RedirectBox::clear_redirects() +{ + string prompt; + vector choices; + + if (dynamic_cast(&_route) != 0) { + prompt = _("Do you really want to remove all redirects from this track?\n" + "(this cannot be undone)"); + } else { + prompt = _("Do you really want to remove all redirects from this bus?\n" + "(this cannot be undone)"); + } + + choices.push_back (_("Yes, remove them all")); + choices.push_back (_("Cancel")); + + Gtkmmext::Choice prompter (prompt, choices); + + prompter.chosen.connect (Gtk::Main::quit.slot()); + prompter.show_all (); + + Gtk::Main::run (); + + if (prompter.get_choice() == 0) { + _route.clear_redirects (this); + } +} + + +void +RedirectBox::edit_redirect (Redirect* redirect) +{ + Insert *insert; + + if (dynamic_cast(&_route) != 0) { + + if (dynamic_cast (&_route)->freeze_state() == AudioTrack::Frozen) { + return; + } + } + + if ((insert = dynamic_cast (redirect)) == 0) { + + /* its a send */ + + if (!_session.engine().connected()) { + return; + } + + Send *send = dynamic_cast (redirect); + + SendUIWindow *send_ui; + + if (send->get_gui() == 0) { + + string title; + title = compose(_("ardour: %1"), send->name()); + + send_ui = new SendUIWindow (*send, _session); + send_ui->set_title (title); + send->set_gui (send_ui); + + } else { + send_ui = reinterpret_cast (send->get_gui()); + } + + if (send_ui->is_visible()) { + send_ui->get_window().raise (); + } else { + send_ui->show_all (); + } + + } else { + + /* its an insert */ + + PluginInsert *plugin_insert; + PortInsert *port_insert; + + if ((plugin_insert = dynamic_cast (insert)) != 0) { + + PluginUIWindow *plugin_ui; + + if (plugin_insert->get_gui() == 0) { + + string title; + string maker = plugin_insert->plugin().maker(); + string::size_type email_pos; + + if ((email_pos = maker.find_first_of ('<')) != string::npos) { + maker = maker.substr (0, email_pos - 1); + } + + if (maker.length() > 32) { + maker = maker.substr (0, 32); + maker += " ..."; + } + + title = compose(_("ardour: %1: %2 (by %3)"), _route.name(), plugin_insert->name(), maker); + + plugin_ui = new PluginUIWindow (_session.engine(), *plugin_insert); + if (_owner_is_mixer) { + ARDOUR_UI::instance()->the_mixer()->ensure_float (*plugin_ui); + } else { + ARDOUR_UI::instance()->the_editor().ensure_float (*plugin_ui); + } + plugin_ui->set_title (title); + plugin_insert->set_gui (plugin_ui); + + } else { + plugin_ui = reinterpret_cast (plugin_insert->get_gui()); + } + + if (plugin_ui->is_visible()) { + plugin_ui->get_window().raise (); + } else { + plugin_ui->show_all (); + } + + } else if ((port_insert = dynamic_cast (insert)) != 0) { + + if (!_session.engine().connected()) { + ArdourMessage msg (NULL, "nojackdialog", _("Not connected to JACK - no I/O changes are possible")); + return; + } + + PortInsertWindow *io_selector; + + if (port_insert->get_gui() == 0) { + io_selector = new PortInsertWindow (_session, *port_insert); + port_insert->set_gui (io_selector); + + } else { + io_selector = reinterpret_cast (port_insert->get_gui()); + } + + if (io_selector->is_visible()) { + io_selector->get_window().raise (); + } else { + io_selector->show_all (); + } + } + } +} + + diff --git a/gtk2_ardour/redirect_box.h b/gtk2_ardour/redirect_box.h new file mode 100644 index 0000000000..8a8c58f717 --- /dev/null +++ b/gtk2_ardour/redirect_box.h @@ -0,0 +1,175 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_redirect_box__ +#define __ardour_gtk_redirect_box__ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "route_ui.h" +#include "io_selector.h" +#include "enums.h" + +class MotionController; +class PluginSelector; +class RouteRedirectSelection; + +namespace ARDOUR { + class Route; + class Send; + class Insert; + class Session; + class PortInsert; + class Connection; + class Plugin; +} + + +class RedirectBox : public Gtk::HBox +{ + public: + RedirectBox (ARDOUR::Placement, ARDOUR::Session&, ARDOUR::Route &, PluginSelector &, RouteRedirectSelection &, bool owner_is_mixer = false); + ~RedirectBox (); + + void set_width (Width); + + void set_title (const std::string & title); + void set_title_shown (bool flag); + + void update(); + + void select_all_redirects (); + void deselect_all_redirects (); + void select_all_plugins (); + void select_all_inserts (); + void select_all_sends (); + + SigC::Signal1 RedirectSelected; + SigC::Signal1 RedirectUnselected; + + protected: + void set_stuff_from_route (); + + private: + ARDOUR::Route & _route; + ARDOUR::Session & _session; + bool _owner_is_mixer; + + ARDOUR::Placement _placement; + + PluginSelector & _plugin_selector; + RouteRedirectSelection & _rr_selection; + + + Gtk::EventBox redirect_eventbox; + Gtk::HBox redirect_hpacker; + Gtk::CList redirect_display; + Gtk::ScrolledWindow redirect_scroller; + + Width _width; + + SigC::Connection newplug_connection; + + Gtk::Menu *send_action_menu; + void build_send_action_menu (); + + void new_send (); + void show_send_controls (); + + Gtk::Menu *redirect_menu; + vector selection_dependent_items; + Gtk::MenuItem* redirect_paste_item; + gint redirect_menu_map_handler (GdkEventAny *ev); + Gtk::Menu * build_redirect_menu (Gtk::CList&); + void build_redirect_tooltip (Gtk::CList&, Gtk::EventBox&, string); + void show_redirect_menu (gint arg); + + void choose_send (); + void send_io_finished (IOSelector::Result, ARDOUR::Redirect*, IOSelectorWindow*); + void choose_insert (); + void choose_plugin (); + void insert_plugin_chosen (ARDOUR::Plugin *); + + gint redirect_button (GdkEventButton *); + void redirects_changed (void *); + void show_redirect_active (ARDOUR::Redirect *, void *); + void show_redirect_name (void*, ARDOUR::Redirect *); + void add_redirect_to_display (ARDOUR::Redirect *); + + void show_plugin_selector (); + + + string redirect_name (ARDOUR::Redirect&); + + + void remove_redirect_gui (ARDOUR::Redirect *); + + void disconnect_newplug(); + + void redirects_reordered (gint, gint); + gint compute_redirect_sort_keys (); + vector redirect_active_connections; + vector redirect_name_connections; + + bool redirect_drag_in_progress; + void redirect_drag_begin (GdkDragContext*); + void redirect_drag_end (GdkDragContext*); + void all_redirects_active(bool state); + + void cut_redirects (); + void copy_redirects (); + void paste_redirects (); + void clear_redirects (); + void clone_redirects (); + void rename_redirects (); + + void for_selected_redirects (void (RedirectBox::*pmf)(ARDOUR::Redirect*)); + void get_selected_redirects (vector&); + + + void activate_redirect (ARDOUR::Redirect*); + void deactivate_redirect (ARDOUR::Redirect*); + void cut_redirect (ARDOUR::Redirect*); + void copy_redirect (ARDOUR::Redirect*); + void edit_redirect (ARDOUR::Redirect*); + void hide_redirect_editor (ARDOUR::Redirect*); + void rename_redirect (ARDOUR::Redirect*); + + gint idle_delete_redirect (ARDOUR::Redirect *); + + void wierd_plugin_dialog (ARDOUR::Plugin& p, uint32_t streams, ARDOUR::IO& io); + +}; + +#endif /* __ardour_gtk_redirect_box__ */ diff --git a/gtk2_ardour/redirect_selection.h b/gtk2_ardour/redirect_selection.h new file mode 100644 index 0000000000..3695f85c60 --- /dev/null +++ b/gtk2_ardour/redirect_selection.h @@ -0,0 +1,12 @@ +#ifndef __ardour_gtk_redirect_selection_h__ +#define __ardour_gtk_redirect_selection_h__ + +#include + +namespace ARDOUR { + class Redirect; +} + +struct RedirectSelection : list {}; + +#endif /* __ardour_gtk_redirect_selection_h__ */ diff --git a/gtk2_ardour/region_editor.cc b/gtk2_ardour/region_editor.cc new file mode 100644 index 0000000000..1cd6447362 --- /dev/null +++ b/gtk2_ardour/region_editor.cc @@ -0,0 +1,739 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include + +#include "region_editor.h" +#include "regionview.h" +#include "ardour_ui.h" +#include "utils.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace SigC; +using namespace std; + +AudioRegionEditor::AudioRegionEditor (Session&s, AudioRegion& r, AudioRegionView& rv) + : ArdourDialog ("audio region editor"), + _session (s), + _region (r), + _region_view (rv), + name_label (_("NAME:")), + lock_button (_("lock")), + mute_button (_("mute")), + opaque_button (_("opaque")), + raise_arrow (GTK_ARROW_UP, GTK_SHADOW_OUT), + lower_arrow (GTK_ARROW_DOWN, GTK_SHADOW_OUT), + layer_label (_("Layer")), + audition_label (_("play")), + time_table (3, 2), + start_clock ("AudioRegionEditorClock", true), + end_clock ("AudioRegionEditorClock", true), + length_clock ("AudioRegionEditorClock", true, true), + sync_offset_clock ("AudioRegionEditorClock", true, true), + envelope_loop_table (1, 3), + envelope_label (_("ENVELOPE")), + fade_in_table (4, 3), + fade_in_length_adjustment (5.0, 0.0, 10000, 0.05, 1), + fade_in_length_spinner (fade_in_length_adjustment, 10), + fade_out_table (4, 3), + fade_out_length_adjustment (5.0, 0.0, 10000, 0.05, 1), + fade_out_length_spinner (fade_out_length_adjustment, 10) + +{ + start_clock.set_session (&_session); + end_clock.set_session (&_session); + length_clock.set_session (&_session); + + name_entry.set_name ("AudioRegionEditorEntry"); + name_label.set_name ("AudioRegionEditorLabel"); + + name_entry.focus_in_event.connect (slot (*this, &AudioRegionEditor::focus_change)); + name_entry.focus_out_event.connect (slot (*this, &AudioRegionEditor::focus_change)); + + name_hbox.set_spacing (5); + name_hbox.pack_start (name_label, false, false); + name_hbox.pack_start (name_entry, false, false); + + raise_button.add (raise_arrow); + lower_button.add (lower_arrow); + layer_frame.set_name ("BaseFrame"); + layer_frame.set_shadow_type (GTK_SHADOW_IN); + layer_frame.add (layer_value_label); + layer_label.set_name ("AudioRegionEditorLabel"); + layer_value_label.set_name ("AudioRegionEditorLabel"); + Gtkmmext::set_usize_to_display_given_text (layer_value_label, "99", 5, 2); + + layer_hbox.set_spacing (5); + layer_hbox.pack_start (layer_label, false, false); + layer_hbox.pack_start (layer_frame, false, false); +#if 0 + layer_hbox.pack_start (raise_button, false, false); + layer_hbox.pack_start (lower_button, false, false); +#endif + + audition_button.add (audition_label); + + mute_button.set_name ("AudioRegionEditorToggleButton"); + opaque_button.set_name ("AudioRegionEditorToggleButton"); + lock_button.set_name ("AudioRegionEditorToggleButton"); + envelope_active_button.set_name ("AudioRegionEditorToggleButton"); + envelope_view_button.set_name ("AudioRegionEditorToggleButton"); + fade_in_active_button.set_name ("AudioRegionEditorToggleButton"); + fade_out_active_button.set_name ("AudioRegionEditorToggleButton"); + audition_button.set_name ("AudioRegionEditorToggleButton"); + + ARDOUR_UI::instance()->tooltips().set_tip (mute_button, _("mute this region")); + ARDOUR_UI::instance()->tooltips().set_tip (opaque_button, _("regions underneath this one cannot be heard")); + ARDOUR_UI::instance()->tooltips().set_tip (lock_button, _("prevent any changes to this region")); + ARDOUR_UI::instance()->tooltips().set_tip (envelope_active_button, _("use the gain envelope during playback")); + ARDOUR_UI::instance()->tooltips().set_tip (envelope_view_button, _("show the gain envelope")); + ARDOUR_UI::instance()->tooltips().set_tip (fade_in_active_button, _("use fade in curve during playback")); + ARDOUR_UI::instance()->tooltips().set_tip (fade_out_active_button, _("use fade out curve during playback")); + ARDOUR_UI::instance()->tooltips().set_tip (audition_button, _("audition this region")); + + mute_button.unset_flags (GTK_CAN_FOCUS); + opaque_button.unset_flags (GTK_CAN_FOCUS); + lock_button.unset_flags (GTK_CAN_FOCUS); + envelope_active_button.unset_flags (GTK_CAN_FOCUS); + envelope_view_button.unset_flags (GTK_CAN_FOCUS); + fade_in_active_button.unset_flags (GTK_CAN_FOCUS); + fade_out_active_button.unset_flags (GTK_CAN_FOCUS); + audition_button.unset_flags (GTK_CAN_FOCUS); + + mute_button.set_events (mute_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + opaque_button.set_events (opaque_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + lock_button.set_events (lock_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + envelope_active_button.set_events (envelope_active_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + envelope_view_button.set_events (envelope_view_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + fade_in_active_button.set_events (fade_in_active_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + fade_out_active_button.set_events (fade_out_active_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + audition_button.set_events (audition_button.get_events() & ~(GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK)); + + top_row_button_hbox.set_border_width (5); + top_row_button_hbox.set_spacing (5); + top_row_button_hbox.set_homogeneous (false); + top_row_button_hbox.pack_start (mute_button, false, false); + top_row_button_hbox.pack_start (opaque_button, false, false); + top_row_button_hbox.pack_start (lock_button, false, false); + top_row_button_hbox.pack_start (layer_hbox, false, false, 5); + top_row_button_hbox.pack_end (audition_button, false, false); + + top_row_hbox.pack_start (name_hbox, true, true); + top_row_hbox.pack_end (top_row_button_hbox, true, true); + + start_label.set_name ("AudioRegionEditorLabel"); + start_label.set_text (_("START:")); + end_label.set_name ("AudioRegionEditorLabel"); + end_label.set_text (_("END:")); + length_label.set_name ("AudioRegionEditorLabel"); + length_label.set_text (_("LENGTH:")); + + time_table.set_col_spacings (2); + time_table.set_row_spacings (5); + time_table.set_border_width (5); + + start_alignment.set (1.0, 0.5); + end_alignment.set (1.0, 0.5); + length_alignment.set (1.0, 0.5); + + start_alignment.add (start_label); + end_alignment.add (end_label); + length_alignment.add (length_label); + + time_table.attach (start_alignment, 0, 1, 0, 1); + time_table.attach (start_clock, 1, 2, 0, 1, 0, 0); + + time_table.attach (end_alignment, 0, 1, 1, 2); + time_table.attach (end_clock, 1, 2, 1, 2, 0, 0); + + time_table.attach (length_alignment, 0, 1, 2, 3); + time_table.attach (length_clock, 1, 2, 2, 3, 0, 0); + + envelope_label.set_name ("AudioRegionEditorLabel"); + + envelope_active_button_label.set_text (_("active")); + envelope_active_button.add (envelope_active_button_label); + envelope_view_button_label.set_text (_("visible")); + envelope_view_button.add (envelope_view_button_label); + + envelope_loop_table.set_border_width (5); + envelope_loop_table.set_row_spacings (2); + envelope_loop_table.attach (envelope_label, 0, 1, 0, 1, 0, 0); + envelope_loop_table.attach (envelope_active_button, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND, 0); + envelope_loop_table.attach (envelope_view_button, 0, 1, 2, 3, GTK_FILL|GTK_EXPAND, 0); + + /* fade in */ + + fade_in_table.set_border_width (5); + fade_in_table.set_homogeneous (false); + + fade_in_label.set_name ("AudioRegionEditorLabel"); + fade_in_active_button_label.set_name ("AudioRegionEditorSmallLabel"); + fade_in_length_label.set_name ("AudioRegionEditorSmallLabel"); + + fade_in_label.set_text (_("FADE IN")); + fade_in_active_button_label.set_text (_("active")); + fade_in_length_label.set_text (_("msecs")); + + fade_in_active_button.add (fade_in_active_button_label); + + fade_in_length_spinner.set_name("GenericSpinner"); + + fade_in_length_spinner.set_digits (3); + + fade_in_length_spinner.focus_in_event.connect (slot (*this, &AudioRegionEditor::focus_change)); + fade_in_length_spinner.focus_out_event.connect (slot (*this, &AudioRegionEditor::focus_change)); + fade_in_length_spinner.activate.connect (slot (*this, &AudioRegionEditor::activation)); + + Gtkmmext::set_usize_to_display_given_text (fade_in_length_spinner, "500g", 20, -1); + + fade_in_label_align.add (fade_in_label); + fade_in_label_align.set (0.5); + + + fade_in_table.attach (fade_in_label_align, 0, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0, 0, 0); + + fade_in_table.attach (fade_in_length_label, 0, 1, 1, 2, GTK_EXPAND, 0, 0, 0); + fade_in_table.attach (fade_in_length_spinner, 0, 1, 2, 3, GTK_FILL|GTK_EXPAND, 0, 0, 0); + + fade_in_table.attach (fade_in_active_button, 0, 2, 3, 5, GTK_FILL|GTK_EXPAND, 0); + + /* fade out */ + + fade_out_table.set_border_width (5); + fade_out_table.set_homogeneous (false); + + fade_out_label.set_name ("AudioRegionEditorLabel"); + fade_out_active_button_label.set_name ("AudioRegionEditorSmallLabel"); + fade_out_length_label.set_name ("AudioRegionEditorSmallLabel"); + + fade_out_label.set_text (_("FADE OUT")); + fade_out_active_button_label.set_text (_("active")); + fade_out_length_label.set_text (_("msecs")); + + fade_out_active_button.add (fade_out_active_button_label); + + fade_out_length_spinner.set_name("GenericSpinner"); + + fade_out_length_spinner.set_digits (3); + + fade_out_length_spinner.focus_in_event.connect (slot (*this, &AudioRegionEditor::focus_change)); + fade_out_length_spinner.focus_out_event.connect (slot (*this, &AudioRegionEditor::focus_change)); + fade_out_length_spinner.activate.connect (slot (*this, &AudioRegionEditor::activation)); + + Gtkmmext::set_usize_to_display_given_text (fade_out_length_spinner, "500g", 20, -1); + + fade_out_label_align.add (fade_out_label); + fade_out_label_align.set (0.5); + + fade_out_table.attach (fade_out_label_align, 0, 2, 0, 1, GTK_FILL|GTK_EXPAND, 0, 0, 0); + + fade_out_table.attach (fade_out_length_label, 0, 1, 1, 2, GTK_EXPAND, 0, 0, 0); + fade_out_table.attach (fade_out_length_spinner, 0, 1, 2, 3, GTK_FILL|GTK_EXPAND, 0, 0, 0); + + fade_out_table.attach (fade_out_active_button, 0, 2, 3, 5, GTK_FILL|GTK_EXPAND, 0); + + lower_hbox.pack_start (time_table, true, true); + lower_hbox.pack_start (sep1, false, false); + lower_hbox.pack_start (envelope_loop_table, true, true); + lower_hbox.pack_start (sep2, false, false); + lower_hbox.pack_start (fade_in_table, true, true); + lower_hbox.pack_start (fade_out_table, true, true); + + upper_vbox.pack_start (top_row_hbox, true, true); + upper_vbox.pack_start (sep3, false, false); + upper_vbox.pack_start (lower_hbox, true, true); + + add (upper_vbox); + set_name ("AudioRegionEditorWindow"); + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK); + + delete_event.connect (bind (slot (just_hide_it), static_cast (this))); + + string title = _("ardour: region "); + title += _region.name(); + set_title (title); + + name_changed (); + bounds_changed (Change (StartChanged|LengthChanged|PositionChanged)); + envelope_active_changed (); + mute_changed (); + opacity_changed (); + lock_changed (); + layer_changed (); + fade_in_changed (); + fade_out_changed (); + + XMLNode *node = _region.extra_xml ("GUI"); + XMLProperty *prop = 0; + bool showing_envelope = false; + + if (node && (prop = node->property ("envelope-visible")) != 0) { + if (prop->value() == "yes") { + showing_envelope = true; + } + } + + if (showing_envelope) { + envelope_view_button.set_active (true); + } else { + envelope_view_button.set_active (false); + } + + _region.StateChanged.connect (slot (*this, &AudioRegionEditor::region_changed)); + + spin_arrow_grab = false; + + connect_editor_events (); +} + +AudioRegionEditor::~AudioRegionEditor () +{ +} + +void +AudioRegionEditor::region_changed (Change what_changed) +{ + if (what_changed & NameChanged) { + name_changed (); + } + if (what_changed & BoundsChanged) { + bounds_changed (what_changed); + } + + if (what_changed & Region::OpacityChanged) { + opacity_changed (); + } + if (what_changed & Region::MuteChanged) { + mute_changed (); + } + if (what_changed & Region::LockChanged) { + lock_changed (); + } + if (what_changed & Region::LayerChanged) { + layer_changed (); + } + + if (what_changed & AudioRegion::EnvelopeActiveChanged) { + envelope_active_changed (); + } + if (what_changed & AudioRegion::FadeInChanged) { + fade_in_changed (); + } + if (what_changed & AudioRegion::FadeOutChanged) { + fade_out_changed (); + } + if (what_changed & AudioRegion::FadeInActiveChanged) { + fade_in_active_changed (); + } + if (what_changed & AudioRegion::FadeOutActiveChanged) { + fade_out_active_changed (); + } +} + +void +AudioRegionEditor::fade_in_realized () +{ + fade_in_changed (); +} + +void +AudioRegionEditor::fade_out_realized () +{ + fade_out_changed (); +} + +gint +AudioRegionEditor::bpressed (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)()) +{ + switch (ev->button) { + case 1: + case 2: + case 3: + if (ev->type == GDK_BUTTON_PRESS) { /* no double clicks here */ + if (!spin_arrow_grab) { + if ((ev->window == but->gtkobj()->panel)) { + spin_arrow_grab = true; + (this->*pmf)(); + } + } + } + break; + default: + break; + } + return FALSE; +} + +gint +AudioRegionEditor::breleased (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)()) +{ + if (spin_arrow_grab) { + (this->*pmf)(); + spin_arrow_grab = false; + } + return FALSE; +} + +void +AudioRegionEditor::start_editing_fade_in () +{ + _region.freeze (); +} + +void +AudioRegionEditor::stop_editing_fade_in () +{ + _region.thaw (_("fade in edit")); +} + +void +AudioRegionEditor::start_editing_fade_out () +{ + _region.freeze (); +} + +void +AudioRegionEditor::stop_editing_fade_out () +{ + _region.thaw (_("fade out edit")); +} + +void +AudioRegionEditor::connect_editor_events () +{ + name_entry.changed.connect (slot (*this, &AudioRegionEditor::name_entry_changed)); + + start_clock.ValueChanged.connect (slot (*this, &AudioRegionEditor::start_clock_changed)); + end_clock.ValueChanged.connect (slot (*this, &AudioRegionEditor::end_clock_changed)); + length_clock.ValueChanged.connect (slot (*this, &AudioRegionEditor::length_clock_changed)); + + fade_in_length_spinner.button_press_event.connect (bind (slot (*this, &AudioRegionEditor::bpressed), &fade_in_length_spinner, + &AudioRegionEditor::start_editing_fade_in)); + fade_in_length_spinner.button_release_event.connect (bind (slot (this, &AudioRegionEditor::breleased), &fade_in_length_spinner, + &AudioRegionEditor::stop_editing_fade_in)); + + fade_out_length_spinner.button_press_event.connect (bind (slot (*this, &AudioRegionEditor::bpressed), &fade_out_length_spinner, + &AudioRegionEditor::start_editing_fade_out)); + fade_out_length_spinner.button_release_event.connect (bind (slot (this, &AudioRegionEditor::breleased), &fade_out_length_spinner, + &AudioRegionEditor::stop_editing_fade_out)); + + fade_in_length_adjustment.value_changed.connect (slot (*this, &AudioRegionEditor::fade_in_length_adjustment_changed)); + fade_out_length_adjustment.value_changed.connect (slot (*this, &AudioRegionEditor::fade_out_length_adjustment_changed)); + + fade_in_active_button.toggled.connect (slot (*this, &AudioRegionEditor::fade_in_active_toggled)); + fade_out_active_button.toggled.connect (slot (*this, &AudioRegionEditor::fade_out_active_toggled)); + + envelope_active_button.button_press_event.connect (slot (*this, &AudioRegionEditor::envelope_active_button_press)); + envelope_active_button.button_release_event.connect (slot (*this, &AudioRegionEditor::envelope_active_button_release)); + audition_button.toggled.connect (slot (*this, &AudioRegionEditor::audition_button_toggled)); + envelope_view_button.toggled.connect (slot (*this, &AudioRegionEditor::envelope_view_button_toggled)); + lock_button.clicked.connect (slot (*this, &AudioRegionEditor::lock_button_clicked)); + mute_button.clicked.connect (slot (*this, &AudioRegionEditor::mute_button_clicked)); + opaque_button.clicked.connect (slot (*this, &AudioRegionEditor::opaque_button_clicked)); + raise_button.clicked.connect (slot (*this, &AudioRegionEditor::raise_button_clicked)); + lower_button.clicked.connect (slot (*this, &AudioRegionEditor::lower_button_clicked)); +} + +void +AudioRegionEditor::start_clock_changed () +{ + _region.set_position (start_clock.current_time(), this); +} + +void +AudioRegionEditor::end_clock_changed () +{ + _region.trim_end (end_clock.current_time(), this); + + end_clock.set (_region.position() + _region.length(), true); +} + +void +AudioRegionEditor::length_clock_changed () +{ + jack_nframes_t frames = length_clock.current_time(); + _region.trim_end (_region.position() + frames, this); + + length_clock.set (_region.length()); +} + +gint +AudioRegionEditor::envelope_active_button_press(GdkEventButton *ev) +{ + return stop_signal (envelope_active_button, "button_press_event"); +} + +gint +AudioRegionEditor::envelope_active_button_release (GdkEventButton *ev) +{ + _region.set_envelope_active (!_region.envelope_active()); + return stop_signal (envelope_active_button, "button_release_event"); +} + +void +AudioRegionEditor::envelope_view_button_toggled () +{ + bool visible = envelope_view_button.get_active (); + + _region_view.set_envelope_visible (visible); +} + +void +AudioRegionEditor::audition_button_toggled () +{ + if (audition_button.get_active()) { + _session.audition_region (_region); + } else { + _session.cancel_audition (); + } +} + +void +AudioRegionEditor::raise_button_clicked () +{ + _region.raise (); +} + +void +AudioRegionEditor::lower_button_clicked () +{ + _region.lower (); +} + +void +AudioRegionEditor::opaque_button_clicked () +{ + bool ractive = _region.opaque(); + + if (opaque_button.get_active() != ractive) { + _region.set_opaque (!ractive); + } +} + +void +AudioRegionEditor::mute_button_clicked () +{ + bool ractive = _region.muted(); + + if (mute_button.get_active() != ractive) { + _region.set_muted (!ractive); + } +} + +void +AudioRegionEditor::lock_button_clicked () +{ + bool ractive = _region.locked(); + + if (lock_button.get_active() != ractive) { + _region.set_locked (!ractive); + } +} + +void +AudioRegionEditor::layer_changed () +{ + char buf[8]; + snprintf (buf, sizeof(buf), "%d", (int) _region.layer() + 1); + layer_value_label.set_text (buf); +} + +void +AudioRegionEditor::name_changed () +{ + if (name_entry.get_text() != _region.name()) { + name_entry.set_text (_region.name()); + } +} + +void +AudioRegionEditor::lock_changed () +{ + bool yn; + + if ((yn = _region.locked()) != lock_button.get_active()) { + lock_button.set_active (yn); + } + + start_clock.set_sensitive (!yn); + end_clock.set_sensitive (!yn); + length_clock.set_sensitive (!yn); +} + +void +AudioRegionEditor::envelope_active_changed () +{ + bool yn; + + if ((yn = _region.envelope_active()) != envelope_active_button.get_active()) { + envelope_active_button.set_active (yn); + } +} + +void +AudioRegionEditor::opacity_changed () +{ + bool yn; + if ((yn = _region.opaque()) != opaque_button.get_active()) { + opaque_button.set_active (yn); + } +} + +void +AudioRegionEditor::mute_changed () +{ + bool yn; + if ((yn = _region.muted()) != mute_button.get_active()) { + mute_button.set_active (yn); + } +} + +void +AudioRegionEditor::bounds_changed (Change what_changed) +{ + if (what_changed & Change ((PositionChanged|LengthChanged))) { + start_clock.set (_region.position(), true); + end_clock.set (_region.position() + _region.length(), true); + length_clock.set (_region.length(), true); + } +} + +gint +AudioRegionEditor::focus_change (GdkEventFocus *ev) +{ + if (ev->in) { + ARDOUR_UI::instance()->allow_focus (true); + } else { + ARDOUR_UI::instance()->allow_focus (false); + } + return TRUE; +} + +void +AudioRegionEditor::activation () +{ + ARDOUR_UI::instance()->allow_focus (false); +} + +void +AudioRegionEditor::name_entry_changed () +{ + if (name_entry.get_text() != _region.name()) { + _region.set_name (name_entry.get_text()); + } +} + +void +AudioRegionEditor::fade_in_changed () +{ + float msecs = fade_in_length_adjustment.get_value(); + jack_nframes_t sr = _session.frame_rate(); + jack_nframes_t adj_frames = (jack_nframes_t) floor (msecs * (sr/1000.0f)); + jack_nframes_t frames; + bool x; + + if (adj_frames != (frames = (jack_nframes_t) _region.fade_in().back()->when)) { + fade_in_length_adjustment.set_value ((frames * 1000.0f) / sr); + } + + if ((x = _region.fade_in_active()) != fade_in_active_button.get_active()) { + fade_in_active_button.set_active (x); + } +} + +void +AudioRegionEditor::fade_out_changed () +{ + float msecs = fade_out_length_adjustment.get_value(); + jack_nframes_t sr = _session.frame_rate(); + jack_nframes_t adj_frames = (jack_nframes_t) floor (msecs * (sr/1000.0f)); + jack_nframes_t frames; + bool x; + if (adj_frames != (frames = (jack_nframes_t) _region.fade_out().back()->when)) { + fade_out_length_adjustment.set_value ((frames * 1000.0f) / sr); + } + + if ((x = _region.fade_out_active()) != fade_out_active_button.get_active()) { + fade_out_active_button.set_active (x); + } +} + +void +AudioRegionEditor::fade_in_length_adjustment_changed () +{ + jack_nframes_t fade_length = (jack_nframes_t) floor (fade_in_length_adjustment.get_value() * _session.frame_rate() * 0.001); + fade_length = max (fade_length, (jack_nframes_t) 64); + fade_length = min (fade_length, _region.length()); + + _region.set_fade_in_length (fade_length); + /* region is frozen, no worries */ + fade_in_changed(); +} + +void +AudioRegionEditor::fade_out_length_adjustment_changed () +{ + jack_nframes_t fade_length = (jack_nframes_t) floor (fade_out_length_adjustment.get_value() * _session.frame_rate() * 0.001); + fade_length = max (fade_length, (jack_nframes_t) 64); + fade_length = min (fade_length, _region.length()); + + _region.set_fade_out_length (fade_length); + /* region is frozen, no worries */ + fade_out_changed(); +} + +void +AudioRegionEditor::fade_in_active_toggled () +{ + _region.set_fade_in_active (fade_in_active_button.get_active()); +} + +void +AudioRegionEditor::fade_out_active_toggled () +{ + _region.set_fade_out_active (fade_out_active_button.get_active()); +} + +void +AudioRegionEditor::fade_out_active_changed () +{ + bool x; + + if ((x = _region.fade_out_active()) != fade_out_active_button.get_active()) { + fade_out_active_button.set_active (x); + } +} + +void +AudioRegionEditor::fade_in_active_changed () +{ + bool x; + + if ((x = _region.fade_in_active()) != fade_in_active_button.get_active()) { + fade_in_active_button.set_active (x); + } +} diff --git a/gtk2_ardour/region_editor.h b/gtk2_ardour/region_editor.h new file mode 100644 index 0000000000..2f01ff1686 --- /dev/null +++ b/gtk2_ardour/region_editor.h @@ -0,0 +1,178 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __gtk_ardour_region_edit_h__ +#define __gtk_ardour_region_edit_h__ + +#include + +#include +#include +#include + +#include "audio_clock.h" +#include "ardour_dialog.h" + +namespace ARDOUR { + class AudioRegion; + class Session; +} + +class AudioRegionView; + +class AudioRegionEditor : public ArdourDialog +{ + public: + AudioRegionEditor (ARDOUR::Session&, ARDOUR::AudioRegion&, AudioRegionView& rv); + ~AudioRegionEditor (); + + private: + ARDOUR::Session& _session; + ARDOUR::AudioRegion& _region; + AudioRegionView& _region_view; + + void connect_editor_events (); + + Gtk::Label name_label; + Gtk::Entry name_entry; + Gtk::HBox name_hbox; + + Gtk::HBox top_row_hbox; + Gtk::HBox top_row_button_hbox; + + Gtk::ToggleButton lock_button; + Gtk::ToggleButton mute_button; + Gtk::ToggleButton opaque_button; + Gtk::ToggleButton envelope_active_button; + Gtk::ToggleButton envelope_view_button; + Gtk::Label envelope_active_button_label; + Gtk::Label envelope_view_button_label; + + Gtk::Button raise_button; + Gtk::Arrow raise_arrow; + Gtk::Button lower_button; + Gtk::Arrow lower_arrow; + Gtk::Frame layer_frame; + Gtk::Label layer_value_label; + Gtk::Label layer_label; + Gtk::HBox layer_hbox; + + Gtk::ToggleButton audition_button; + Gtk::Label audition_label; + + Gtk::VBox upper_vbox; + Gtk::HBox lower_hbox; + + Gtk::Table time_table; + + Gtk::Label start_label; + Gtk::Label end_label; + Gtk::Label length_label; + Gtk::Alignment start_alignment; + Gtk::Alignment end_alignment; + Gtk::Alignment length_alignment; + + AudioClock start_clock; + AudioClock end_clock; + AudioClock length_clock; + AudioClock sync_offset_clock; + + Gtk::Table envelope_loop_table; + Gtk::Button loop_button; + Gtk::Label loop_label; + Gtk::Label envelope_label; + + Gtk::Table fade_in_table; + Gtk::Label fade_in_label; + Gtk::Alignment fade_in_label_align; + Gtk::Label fade_in_active_button_label; + Gtk::ToggleButton fade_in_active_button; + Gtk::Label fade_in_length_label; + + Gtk::Adjustment fade_in_length_adjustment; + Gtk::SpinButton fade_in_length_spinner; + + Gtk::Table fade_out_table; + Gtk::Label fade_out_label; + Gtk::Alignment fade_out_label_align; + Gtk::Label fade_out_active_button_label; + Gtk::ToggleButton fade_out_active_button; + Gtk::Label fade_out_length_label; + + Gtk::Adjustment fade_out_length_adjustment; + Gtk::SpinButton fade_out_length_spinner; + + Gtk::HSeparator sep3; + Gtk::VSeparator sep1; + Gtk::VSeparator sep2; + + void region_changed (ARDOUR::Change); + void bounds_changed (ARDOUR::Change); + void name_changed (); + void opacity_changed (); + void mute_changed (); + void envelope_active_changed (); + void lock_changed (); + void layer_changed (); + + void fade_in_length_adjustment_changed (); + void fade_out_length_adjustment_changed (); + void fade_in_changed (); + void fade_out_changed (); + + gint focus_change (GdkEventFocus *); + void activation (); + + void name_entry_changed (); + void start_clock_changed (); + void end_clock_changed (); + void length_clock_changed (); + + gint envelope_active_button_press (GdkEventButton *); + gint envelope_active_button_release (GdkEventButton *); + + void audition_button_toggled (); + void envelope_view_button_toggled (); + void lock_button_clicked (); + void mute_button_clicked (); + void opaque_button_clicked (); + void raise_button_clicked (); + void lower_button_clicked (); + + void fade_in_active_toggled (); + void fade_out_active_toggled (); + void fade_in_active_changed (); + void fade_out_active_changed (); + + void fade_in_realized (); + void fade_out_realized (); + + void start_editing_fade_in (); + void start_editing_fade_out (); + void stop_editing_fade_in (); + void stop_editing_fade_out (); + + gint bpressed (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)()); + gint breleased (GdkEventButton* ev, Gtk::SpinButton* but, void (AudioRegionEditor::*pmf)()); + + bool spin_arrow_grab; +}; + +#endif /* __gtk_ardour_region_edit_h__ */ diff --git a/gtk2_ardour/region_gain_line.cc b/gtk2_ardour/region_gain_line.cc new file mode 100644 index 0000000000..c3d81bbf8a --- /dev/null +++ b/gtk2_ardour/region_gain_line.cc @@ -0,0 +1,96 @@ +#include +#include + +#include "region_gain_line.h" +#include "regionview.h" +#include "utils.h" + +#include "time_axis_view.h" +#include "editor.h" + +#include + + +#include "i18n.h" + + +using namespace std; +using namespace ARDOUR; + +AudioRegionGainLine::AudioRegionGainLine (string name, Session& s, AudioRegionView& r, GtkCanvasItem* parent, + Curve& c, + gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer), + gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer)) + : AutomationLine (name, r.get_time_axis_view(), parent, c, point_callback, line_callback), + session (s), + rv (r) +{ + gtk_canvas_item_raise_to_top (group); + set_verbose_cursor_uses_gain_mapping (true); + terminal_points_can_slide = false; +} + +void +AudioRegionGainLine::view_to_model_y (double& y) +{ + y = slider_position_to_gain (y); + y = max (0.0, y); + y = min (2.0, y); +} + +void +AudioRegionGainLine::model_to_view_y (double& y) +{ + y = gain_to_slider_position (y); +} + +void +AudioRegionGainLine::start_drag (ControlPoint* cp, float fraction) +{ + AutomationLine::start_drag(cp,fraction); + if (!rv.region.envelope_active()) { + trackview.session().add_undo( bind( slot(rv.region, &AudioRegion::set_envelope_active), false) ); + } +} + +// This is an extended copy from AutomationList +void +AudioRegionGainLine::remove_point (ControlPoint& cp) +{ + ModelRepresentation mr; + + model_representation (cp, mr); + + trackview.editor.current_session()->begin_reversible_command (_("remove control point")); + trackview.editor.current_session()->add_undo (get_memento()); + + if (!rv.region.envelope_active()) { + trackview.session().add_undo( bind( slot(rv.region, &AudioRegion::set_envelope_active), false) ); + trackview.session().add_redo( bind( slot(rv.region, &AudioRegion::set_envelope_active), true) ); + rv.region.set_envelope_active(true); + } + + alist.erase (mr.start, mr.end); + + trackview.editor.current_session()->add_redo_no_execute (get_memento()); + trackview.editor.current_session()->commit_reversible_command (); + trackview.editor.current_session()->set_dirty (); +} + +void +AudioRegionGainLine::end_drag (ControlPoint* cp) +{ + if (!rv.region.envelope_active()) { + trackview.session().add_redo( bind( slot(rv.region, &AudioRegion::set_envelope_active), true) ); + rv.region.set_envelope_active(true); + } + AutomationLine::end_drag(cp); +} + + +// This is a copy from AutomationList +UndoAction +AudioRegionGainLine::get_memento () +{ + return alist.get_memento(); +} diff --git a/gtk2_ardour/region_gain_line.h b/gtk2_ardour/region_gain_line.h new file mode 100644 index 0000000000..455be65c9d --- /dev/null +++ b/gtk2_ardour/region_gain_line.h @@ -0,0 +1,43 @@ +#ifndef __ardour_gtk_region_gain_line_h__ +#define __ardour_gtk_region_gain_line_h__ + +#include +#include +#include + +#include "automation_line.h" + +namespace ARDOUR { + class Session; +} + +class TimeAxisView; +class AudioRegionView; + +class AudioRegionGainLine : public AutomationLine +{ + public: + AudioRegionGainLine (string name, ARDOUR::Session&, AudioRegionView&, GtkCanvasItem* parent, + ARDOUR::Curve&, + gint (*point_callback)(GtkCanvasItem*, GdkEvent*, gpointer), + gint (*line_callback)(GtkCanvasItem*, GdkEvent*, gpointer)); + + void view_to_model_y (double&); + void model_to_view_y (double&); + + void start_drag (ControlPoint*, float fraction); + void end_drag (ControlPoint*); + + void remove_point (ControlPoint&); + + + + private: + ARDOUR::Session& session; + AudioRegionView& rv; + + UndoAction get_memento(); +}; + + +#endif /* __ardour_gtk_region_gain_line_h__ */ diff --git a/gtk2_ardour/region_selection.cc b/gtk2_ardour/region_selection.cc new file mode 100644 index 0000000000..b0afa26999 --- /dev/null +++ b/gtk2_ardour/region_selection.cc @@ -0,0 +1,204 @@ +#include + +#include + +#include "regionview.h" +#include "region_selection.h" + +using namespace ARDOUR; +using namespace SigC; + + +bool +AudioRegionComparator::operator() (const AudioRegionView* a, const AudioRegionView* b) const +{ + if (a == b) { + return false; + } else { + return a < b; + } +} + +AudioRegionSelection::AudioRegionSelection () +{ + _current_start = 0; + _current_end = 0; +} + +AudioRegionSelection::AudioRegionSelection (const AudioRegionSelection& other) +{ + + for (AudioRegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) { + add (*i, false); + } + _current_start = other._current_start; + _current_end = other._current_end; +} + + + +AudioRegionSelection& +AudioRegionSelection::operator= (const AudioRegionSelection& other) +{ + if (this != &other) { + + clear_all(); + + for (AudioRegionSelection::const_iterator i = other.begin(); i != other.end(); ++i) { + add (*i, false); + } + + _current_start = other._current_start; + _current_end = other._current_end; + } + + return *this; +} + +void +AudioRegionSelection::clear_all() +{ + clear(); + _bylayer.clear(); +} + +bool AudioRegionSelection::contains (AudioRegionView* rv) +{ + if (this->find (rv) != end()) { + return true; + } + else { + return false; + } + +} + +void +AudioRegionSelection::add (AudioRegionView* rv, bool dosort) +{ + if (this->find (rv) != end()) { + /* we already have it */ + return; + } + + rv->AudioRegionViewGoingAway.connect (slot (*this, &AudioRegionSelection::remove_it)); + + if (rv->region.first_frame() < _current_start || empty()) { + _current_start = rv->region.first_frame(); + } + + if (rv->region.last_frame() > _current_end || empty()) { + _current_end = rv->region.last_frame(); + } + + insert (rv); + + // add to layer sorted list + add_to_layer (rv); + +} + +void +AudioRegionSelection::remove_it (AudioRegionView *rv) +{ + remove (rv); +} + +bool +AudioRegionSelection::remove (AudioRegionView* rv) +{ + AudioRegionSelection::iterator i; + + if ((i = this->find (rv)) != end()) { + + erase (i); + + // remove from layer sorted list + _bylayer.remove (rv); + + if (empty()) { + + _current_start = 0; + _current_end = 0; + + } else { + + AudioRegion& region ((*i)->region); + + if (region.first_frame() == _current_start) { + + /* reset current start */ + + jack_nframes_t ref = max_frames; + + for (i = begin (); i != end(); ++i) { + if (region.first_frame() < ref) { + ref = region.first_frame(); + } + } + + _current_start = ref; + + } + + if (region.last_frame() == _current_end) { + + /* reset current end */ + + jack_nframes_t ref = 0; + + for (i = begin (); i != end(); ++i) { + if (region.first_frame() > ref) { + ref = region.first_frame(); + } + } + + _current_end = ref; + } + } + + return true; + } + + return false; +} + +void +AudioRegionSelection::add_to_layer (AudioRegionView * rv) +{ + // insert it into layer sorted position + + list::iterator i; + + for (i = _bylayer.begin(); i != _bylayer.end(); ++i) + { + if (rv->region.layer() < (*i)->region.layer()) { + _bylayer.insert(i, rv); + return; + } + } + + // insert at end if we get here + _bylayer.insert(i, rv); +} + +struct RegionSortByTime { + bool operator() (const AudioRegionView* a, const AudioRegionView* b) { + return a->region.position() < b->region.position(); + } +}; + + +void +AudioRegionSelection::by_position (list& foo) const +{ + list::const_iterator i; + RegionSortByTime sorter; + + for (i = _bylayer.begin(); i != _bylayer.end(); ++i) { + foo.push_back (*i); + } + + foo.sort (sorter); + return; +} diff --git a/gtk2_ardour/region_selection.h b/gtk2_ardour/region_selection.h new file mode 100644 index 0000000000..73fabeb0b2 --- /dev/null +++ b/gtk2_ardour/region_selection.h @@ -0,0 +1,56 @@ +#ifndef __ardour_gtk_region_selection_h__ +#define __ardour_gtk_region_selection_h__ + +#include +#include +#include +#include + +using std::list; +using std::set; + +class AudioRegionView; + +struct AudioRegionComparator { + bool operator() (const AudioRegionView* a, const AudioRegionView* b) const; +}; + +class AudioRegionSelection : public set, public SigC::Object +{ + public: + AudioRegionSelection(); + AudioRegionSelection (const AudioRegionSelection&); + + AudioRegionSelection& operator= (const AudioRegionSelection&); + + void add (AudioRegionView*, bool dosort = true); + bool remove (AudioRegionView*); + bool contains (AudioRegionView*); + + void clear_all(); + + jack_nframes_t start () const { + return _current_start; + } + + /* collides with list<>::end */ + + jack_nframes_t end_frame () const { + return _current_end; + } + + const list & by_layer() const { return _bylayer; } + void by_position (list&) const; + + private: + void remove_it (AudioRegionView*); + + void add_to_layer (AudioRegionView *); + + jack_nframes_t _current_start; + jack_nframes_t _current_end; + + list _bylayer; +}; + +#endif /* __ardour_gtk_region_selection_h__ */ diff --git a/gtk2_ardour/regionview.cc b/gtk2_ardour/regionview.cc new file mode 100644 index 0000000000..73856e920d --- /dev/null +++ b/gtk2_ardour/regionview.cc @@ -0,0 +1,1406 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include "streamview.h" +#include "regionview.h" +#include "audio_time_axis.h" +#include "canvas-simplerect.h" +#include "canvas-simpleline.h" +#include "canvas-waveview.h" +#include "public_editor.h" +#include "region_editor.h" +#include "region_gain_line.h" +#include "ghostregion.h" +#include "audio_time_axis.h" +#include "utils.h" +#include "rgb_macros.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace SigC; +using namespace ARDOUR; +using namespace Editing; + +static const int32_t sync_mark_width = 9; + +SigC::Signal1 AudioRegionView::AudioRegionViewGoingAway; + +AudioRegionView::AudioRegionView (GtkCanvasGroup *parent, AudioTimeAxisView &tv, + AudioRegion& r, + double spu, + double amplitude_above_axis, + GdkColor& basic_color, + bool wfw) + + : TimeAxisViewItem (r.name(), parent, tv, spu, basic_color, r.position(), r.length(), + TimeAxisViewItem::Visibility (TimeAxisViewItem::ShowNameText| + TimeAxisViewItem::ShowNameHighlight| + TimeAxisViewItem::ShowFrame)), + + region (r) +{ + GtkCanvasPoints *shape; + XMLNode *node; + + editor = 0; + valid = true; + in_destructor = false; + _amplitude_above_axis = amplitude_above_axis; + zero_line = 0; + wait_for_waves = wfw; + _height = 0; + + _flags = 0; + + if ((node = region.extra_xml ("GUI")) != 0) { + set_flags (node); + } else { + _flags = WaveformVisible; + store_flags (); + } + + if (trackview.editor.new_regionviews_display_gain()) { + _flags |= EnvelopeVisible; + } + + compute_colors (basic_color); + + create_waves (); + + gtk_object_set_data (GTK_OBJECT(name_highlight), "regionview", this); + gtk_object_set_data (GTK_OBJECT(name_text), "regionview", this); + + shape = gtk_canvas_points_new (4); + + /* an equilateral triangle */ + + shape->coords[0] = -((sync_mark_width-1)/2); + shape->coords[1] = 1; + + shape->coords[2] = (sync_mark_width - 1)/2; + shape->coords[3] = 1; + + shape->coords[4] = 0; + shape->coords[5] = sync_mark_width - 1; + + shape->coords[6] = -((sync_mark_width-1)/2); + shape->coords[7] = 1; + + // cerr << "set sync mark al points, nc = " << shape->num_points << endl; + sync_mark = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_polygon_get_type(), + "points", shape, + "fill_color_rgba", fill_color, + NULL); + gtk_canvas_item_hide (sync_mark); + gtk_canvas_points_unref (shape); + + + fade_in_shape = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_polygon_get_type(), + "fill_color_rgba", fade_color, + NULL); + gtk_object_set_data (GTK_OBJECT(fade_in_shape), "regionview", this); + + fade_out_shape = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_polygon_get_type(), + "fill_color_rgba", fade_color, + NULL); + gtk_object_set_data (GTK_OBJECT(fade_out_shape), "regionview", this); + + + + { + uint32_t r,g,b,a; + UINT_TO_RGBA(fill_color,&r,&g,&b,&a); + + + fade_in_handle = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_simplerect_get_type(), + "fill_color_rgba", RGBA_TO_UINT(r,g,b,0), + "outline_pixels", 0, + "y1", 2.0, + "y2", 7.0, + NULL); + gtk_object_set_data (GTK_OBJECT(fade_in_handle), "regionview", this); + + fade_out_handle = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_simplerect_get_type(), + "fill_color_rgba", RGBA_TO_UINT(r,g,b,0), + "outline_pixels", 0, + "y1", 2.0, + "y2", 7.0, + NULL); + gtk_object_set_data (GTK_OBJECT(fade_out_handle), "regionview", this); + } + + string foo = region.name(); + foo += ':'; + foo += "gain"; + + gain_line = new AudioRegionGainLine (foo, tv.session(), *this, group, region.envelope(), + PublicEditor::canvas_control_point_event, + PublicEditor::canvas_line_event); + + if (!(_flags & EnvelopeVisible)) { + gain_line->hide (); + } else { + gain_line->show (); + } + + reset_width_dependent_items ((double) region.length() / samples_per_unit); + + gain_line->reset (); + + set_height (trackview.height); + + region_muted (); + region_sync_changed (); + region_resized (BoundsChanged); + set_waveview_data_src(); + region_locked (); + envelope_active_changed (); + fade_in_active_changed (); + fade_out_active_changed (); + + region.StateChanged.connect (slot (*this, &AudioRegionView::region_changed)); + + gtk_signal_connect (GTK_OBJECT(group), "event", + (GtkSignalFunc) PublicEditor::canvas_region_view_event, + this); + gtk_signal_connect (GTK_OBJECT(name_highlight), "event", + (GtkSignalFunc) PublicEditor::canvas_region_view_name_highlight_event, + this); + + gtk_signal_connect (GTK_OBJECT(name_text), "event", + (GtkSignalFunc) PublicEditor::canvas_region_view_name_event, + this); + + gtk_signal_connect (GTK_OBJECT(fade_in_shape), "event", + (GtkSignalFunc) PublicEditor::canvas_fade_in_event, + this); + + gtk_signal_connect (GTK_OBJECT(fade_in_handle), "event", + (GtkSignalFunc) PublicEditor::canvas_fade_in_handle_event, + this); + + gtk_signal_connect (GTK_OBJECT(fade_out_shape), "event", + (GtkSignalFunc) PublicEditor::canvas_fade_out_event, + this); + + gtk_signal_connect (GTK_OBJECT(fade_out_handle), "event", + (GtkSignalFunc) PublicEditor::canvas_fade_out_handle_event, + this); + + set_colors (); + + /* XXX sync mark drag? */ + +} + +AudioRegionView::~AudioRegionView () +{ + in_destructor = true; + + AudioRegionViewGoingAway (this); /* EMIT_SIGNAL */ + + for (vector::iterator cache = wave_caches.begin(); cache != wave_caches.end() ; ++cache) { + gtk_canvas_waveview_cache_destroy (*cache); + } + + /* all waveviews will be destroyed when the group is destroyed */ + + for (vector::iterator g = ghosts.begin(); g != ghosts.end(); ++g) { + delete *g; + } + + if (editor) { + delete editor; + } + + delete gain_line; +} + +gint +AudioRegionView::_lock_toggle (GtkCanvasItem* item, GdkEvent* ev, void* arg) +{ + switch (ev->type) { + case GDK_BUTTON_RELEASE: + static_cast(arg)->lock_toggle (); + return TRUE; + break; + default: + break; + } + return FALSE; +} + +void +AudioRegionView::lock_toggle () +{ + region.set_locked (!region.locked()); +} + +void +AudioRegionView::region_changed (Change what_changed) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &AudioRegionView::region_changed), what_changed)); + + if (what_changed & BoundsChanged) { + region_resized (what_changed); + region_sync_changed (); + } + if (what_changed & Region::MuteChanged) { + region_muted (); + } + if (what_changed & Region::OpacityChanged) { + region_opacity (); + } + if (what_changed & ARDOUR::NameChanged) { + region_renamed (); + } + if (what_changed & Region::SyncOffsetChanged) { + region_sync_changed (); + } + if (what_changed & Region::LayerChanged) { + region_layered (); + } + if (what_changed & Region::LockChanged) { + region_locked (); + } + if (what_changed & AudioRegion::ScaleAmplitudeChanged) { + region_scale_amplitude_changed (); + } + if (what_changed & AudioRegion::FadeInChanged) { + fade_in_changed (); + } + if (what_changed & AudioRegion::FadeOutChanged) { + fade_out_changed (); + } + if (what_changed & AudioRegion::FadeInActiveChanged) { + fade_in_active_changed (); + } + if (what_changed & AudioRegion::FadeOutActiveChanged) { + fade_out_active_changed (); + } + if (what_changed & AudioRegion::EnvelopeActiveChanged) { + envelope_active_changed (); + } +} + +void +AudioRegionView::fade_in_changed () +{ + reset_fade_in_shape (); +} + +void +AudioRegionView::fade_out_changed () +{ + reset_fade_out_shape (); +} + +void +AudioRegionView::set_fade_in_active (bool yn) +{ + region.set_fade_in_active (yn); +} + +void +AudioRegionView::set_fade_out_active (bool yn) +{ + region.set_fade_out_active (yn); +} + +void +AudioRegionView::fade_in_active_changed () +{ + uint32_t r,g,b,a; + uint32_t col; + UINT_TO_RGBA(fade_color,&r,&g,&b,&a); + + if (region.fade_in_active()) { + col = RGBA_TO_UINT(r,g,b,120); + gtk_canvas_item_set (fade_in_shape, + "fill_color_rgba", col, + "width_pixels", 0, + "outline_color_rgba", RGBA_TO_UINT(r,g,b,0), + NULL); + } else { + col = RGBA_TO_UINT(r,g,b,0); + gtk_canvas_item_set (fade_in_shape, + "fill_color_rgba", col, + "width_pixels", 1, + "outline_color_rgba", RGBA_TO_UINT(r,g,b,255), + NULL); + } +} + +void +AudioRegionView::fade_out_active_changed () +{ + uint32_t r,g,b,a; + uint32_t col; + UINT_TO_RGBA(fade_color,&r,&g,&b,&a); + + if (region.fade_out_active()) { + col = RGBA_TO_UINT(r,g,b,120); + gtk_canvas_item_set (fade_out_shape, + "fill_color_rgba", col, + "width_pixels", 0, + "outline_color_rgba", RGBA_TO_UINT(r,g,b,0), + NULL); + } else { + col = RGBA_TO_UINT(r,g,b,0); + gtk_canvas_item_set (fade_out_shape, + "fill_color_rgba", col, + "width_pixels", 1, + "outline_color_rgba", RGBA_TO_UINT(r,g,b,255), + NULL); + } +} + + +void +AudioRegionView::region_scale_amplitude_changed () +{ + ENSURE_GUI_THREAD (slot (*this, &AudioRegionView::region_scale_amplitude_changed)); + + for (uint32_t n = 0; n < waves.size(); ++n) { + // force a reload of the cache + gtk_canvas_item_set (waves[n], "data_src", ®ion, NULL); + } +} + +void +AudioRegionView::region_locked () +{ + /* name will show locked status */ + region_renamed (); +} + +void +AudioRegionView::region_resized (Change what_changed) +{ + double unit_length; + + if (what_changed & ARDOUR::PositionChanged) { + set_position (region.position(), 0); + } + + if (what_changed & Change (StartChanged|LengthChanged)) { + + set_duration (region.length(), 0); + + unit_length = region.length() / samples_per_unit; + + reset_width_dependent_items (unit_length); + + for (uint32_t n = 0; n < waves.size(); ++n) { + gtk_canvas_item_set (waves[n], "region_start", (guint32) region.start(), NULL); + } + + for (vector::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + + (*i)->set_duration (unit_length); + + for (vector::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) { + gtk_canvas_item_set ((*w), "region_start", region.start(), NULL); + } + } + } +} + +void +AudioRegionView::reset_width_dependent_items (double pixel_width) +{ + TimeAxisViewItem::reset_width_dependent_items (pixel_width); + _pixel_width = pixel_width; + + if (zero_line) { + gtk_canvas_item_set (zero_line, "x2", pixel_width - 1.0, NULL); + } + + if (pixel_width <= 6.0) { + gtk_canvas_item_hide (fade_in_handle); + gtk_canvas_item_hide (fade_out_handle); + } else { + if (_height < 5.0) { + gtk_canvas_item_hide (fade_in_handle); + gtk_canvas_item_hide (fade_out_handle); + } else { + gtk_canvas_item_show (fade_in_handle); + gtk_canvas_item_show (fade_out_handle); + } + } + + reset_fade_shapes (); +} + +void +AudioRegionView::region_layered () +{ + AudioTimeAxisView *atv = dynamic_cast (&get_time_axis_view()); + atv->view->region_layered (this); +} + +void +AudioRegionView::region_muted () +{ + set_frame_color (); + region_renamed (); + + for (uint32_t n=0; n < waves.size(); ++n) { + if (region.muted()) { + gtk_canvas_item_set (waves[n], "wave_color", color_map[cMutedWaveForm], NULL); + } else { + gtk_canvas_item_set (waves[n], "wave_color", color_map[cWaveForm], NULL); + } + } +} + +void +AudioRegionView::region_opacity () +{ + set_frame_color (); +} + +void +AudioRegionView::raise () +{ + region.raise (); +} + +void +AudioRegionView::raise_to_top () +{ + region.raise_to_top (); +} + +void +AudioRegionView::lower () +{ + region.lower (); +} + +void +AudioRegionView::lower_to_bottom () +{ + region.lower_to_bottom (); +} + +bool +AudioRegionView::set_position (jack_nframes_t pos, void* src, double* ignored) +{ + double delta; + bool ret; + + if (!(ret = TimeAxisViewItem::set_position (pos, this, &delta))) { + return false; + } + + if (ignored) { + *ignored = delta; + } + + if (delta) { + for (vector::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + gtk_canvas_item_move ((*i)->group, delta, 0.0); + } + } + + return ret; +} + +void +AudioRegionView::set_height (gdouble height) +{ + uint32_t wcnt = waves.size(); + + TimeAxisViewItem::set_height (height - 2); + + _height = height; + + for (uint32_t n=0; n < wcnt; ++n) { + gdouble ht; + + if ((height) < NAME_HIGHLIGHT_THRESH) { + ht = ((height-2*wcnt) / (double) wcnt); + } else { + ht = (((height-2*wcnt) - NAME_HIGHLIGHT_SIZE) / (double) wcnt); + } + + gdouble yoff = n * (ht+1); + + gtk_canvas_item_set (waves[n], "height", ht, NULL); + gtk_canvas_item_set (waves[n], "y", yoff + 2, NULL); + } + + if ((height/wcnt) < NAME_HIGHLIGHT_SIZE) { + gain_line->hide (); + } else { + if (_flags & EnvelopeVisible) { + gain_line->show (); + } + } + + manage_zero_line (); + gain_line->set_height ((uint32_t) rint (height - NAME_HIGHLIGHT_SIZE)); + reset_fade_shapes (); + + gtk_canvas_item_raise_to_top (name_text) ; +} + +void +AudioRegionView::manage_zero_line () +{ + if (!zero_line) { + return; + } + + if (_height >= 100) { + gdouble wave_midpoint = (_height - NAME_HIGHLIGHT_SIZE) / 2.0; + gtk_canvas_item_set (zero_line, + "y1", wave_midpoint, + "y2", wave_midpoint, + NULL); + gtk_canvas_item_show (zero_line); + } else { + gtk_canvas_item_hide (zero_line); + } +} + +void +AudioRegionView::reset_fade_shapes () +{ + reset_fade_in_shape (); + reset_fade_out_shape (); +} + +void +AudioRegionView::reset_fade_in_shape () +{ + reset_fade_in_shape_width ((jack_nframes_t) region.fade_in().back()->when); +} + +void +AudioRegionView::reset_fade_in_shape_width (jack_nframes_t width) +{ + /* smallest size for a fade is 64 frames */ + + width = std::max ((jack_nframes_t) 64, width); + + GtkCanvasPoints* points; + double pwidth = width / samples_per_unit; + uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth); + double h; + + if (_height < 5) { + gtk_canvas_item_hide (fade_in_shape); + gtk_canvas_item_hide (fade_in_handle); + return; + } + + double handle_center; + handle_center = pwidth; + + if (handle_center > 7.0) { + handle_center -= 3.0; + } else { + handle_center = 3.0; + } + + gtk_canvas_item_set (fade_in_handle, + "x1", handle_center - 3.0, + "x2", handle_center + 3.0, + NULL); + + if (pwidth < 5) { + gtk_canvas_item_hide (fade_in_shape); + return; + } + + gtk_canvas_item_show (fade_in_shape); + + float curve[npoints]; + region.fade_in().get_vector (0, region.fade_in().back()->when, curve, npoints); + + points = get_canvas_points ("fade in shape", npoints+3); + + if (_height > NAME_HIGHLIGHT_THRESH) { + h = _height - NAME_HIGHLIGHT_SIZE; + } else { + h = _height; + } + + /* points *MUST* be in anti-clockwise order */ + + uint32_t pi, pc; + double xdelta = pwidth/npoints; + + for (pi = 0, pc = 0; pc < npoints; ++pc) { + points->coords[pi++] = 1 + (pc * xdelta); + points->coords[pi++] = 2 + (h - (curve[pc] * h)); + } + + /* fold back */ + + points->coords[pi++] = pwidth; + points->coords[pi++] = 2; + + points->coords[pi++] = 1; + points->coords[pi++] = 2; + + /* connect the dots ... */ + + points->coords[pi++] = points->coords[0]; + points->coords[pi] = points->coords[1]; + + gtk_canvas_item_set (fade_in_shape, "points", points, NULL); + gtk_canvas_points_unref (points); +} + +void +AudioRegionView::reset_fade_out_shape () +{ + reset_fade_out_shape_width ((jack_nframes_t) region.fade_out().back()->when); +} + +void +AudioRegionView::reset_fade_out_shape_width (jack_nframes_t width) +{ + /* smallest size for a fade is 64 frames */ + + width = std::max ((jack_nframes_t) 64, width); + + GtkCanvasPoints* points; + double pwidth = width / samples_per_unit; + uint32_t npoints = std::min (gdk_screen_width(), (int) pwidth); + double h; + + if (_height < 5) { + gtk_canvas_item_hide (fade_out_shape); + gtk_canvas_item_hide (fade_out_handle); + return; + } + + double handle_center; + handle_center = (region.length() - width) / samples_per_unit; + + if (handle_center > 7.0) { + handle_center -= 3.0; + } else { + handle_center = 3.0; + } + + gtk_canvas_item_set (fade_out_handle, + "x1", handle_center - 3.0, + "x2", handle_center + 3.0, + NULL); + + /* don't show shape if its too small */ + + if (pwidth < 5) { + gtk_canvas_item_hide (fade_out_shape); + return; + } + + gtk_canvas_item_show (fade_out_shape); + + float curve[npoints]; + region.fade_out().get_vector (0, region.fade_out().back()->when, curve, npoints); + + if (_height > NAME_HIGHLIGHT_THRESH) { + h = _height - NAME_HIGHLIGHT_SIZE; + } else { + h = _height; + } + + /* points *MUST* be in anti-clockwise order */ + + points = get_canvas_points ("fade out shape", npoints+3); + + uint32_t pi, pc; + double xdelta = pwidth/npoints; + + for (pi = 0, pc = 0; pc < npoints; ++pc) { + points->coords[pi++] = _pixel_width - 1 - pwidth + (pc*xdelta); + points->coords[pi++] = 2 + (h - (curve[pc] * h)); + } + + /* fold back */ + + points->coords[pi++] = _pixel_width; + points->coords[pi++] = h; + + points->coords[pi++] = _pixel_width; + points->coords[pi++] = 2; + + /* connect the dots ... */ + + points->coords[pi++] = points->coords[0]; + points->coords[pi] = points->coords[1]; + + gtk_canvas_item_set (fade_out_shape, "points", points, NULL); + gtk_canvas_points_unref (points); +} + +void +AudioRegionView::set_samples_per_unit (gdouble spu) +{ + TimeAxisViewItem::set_samples_per_unit (spu); + + for (uint32_t n=0; n < waves.size(); ++n) { + gtk_canvas_item_set (waves[n], "samples_per_unit", spu, NULL); + } + + for (vector::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + (*i)->set_samples_per_unit (spu); + (*i)->set_duration (region.length() / samples_per_unit); + } + + gain_line->reset (); + reset_fade_shapes (); + region_sync_changed (); +} + +bool +AudioRegionView::set_duration (jack_nframes_t frames, void *src) +{ + if (!TimeAxisViewItem::set_duration (frames, src)) { + return false; + } + + for (vector::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + (*i)->set_duration (region.length() / samples_per_unit); + } + + return true; +} + +void +AudioRegionView::set_amplitude_above_axis (gdouble spp) +{ + for (uint32_t n=0; n < waves.size(); ++n) { + gtk_canvas_item_set (waves[n], "amplitude_above_axis", spp, NULL); + } +} + +void +AudioRegionView::compute_colors (GdkColor& basic_color) +{ + TimeAxisViewItem::compute_colors (basic_color); + uint32_t r, g, b, a; + + /* gain color computed in envelope_active_changed() */ + + UINT_TO_RGBA (fill_color, &r, &g, &b, &a); + fade_color = RGBA_TO_UINT(r,g,b,120); +} + +void +AudioRegionView::set_colors () +{ + TimeAxisViewItem::set_colors (); + + gain_line->set_line_color (region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]); + gtk_canvas_item_set (sync_mark, "fill_color_rgba", fill_color, NULL); + + for (uint32_t n=0; n < waves.size(); ++n) { + if (region.muted()) { + gtk_canvas_item_set (waves[n], "wave_color", color_map[cMutedWaveForm], NULL); + } else { + gtk_canvas_item_set (waves[n], "wave_color", color_map[cWaveForm], NULL); + } + } +} + +void +AudioRegionView::set_frame_color () +{ + if (region.opaque()) { + fill_opacity = 180; + } else { + fill_opacity = 100; + } + + TimeAxisViewItem::set_frame_color (); +} + +void +AudioRegionView::show_region_editor () +{ + if (editor == 0) { + editor = new AudioRegionEditor (trackview.session(), region, *this); + editor->realize (); + trackview.editor.ensure_float (*editor); + } + + editor->show_all (); + editor->get_window().raise(); +} + +void +AudioRegionView::hide_region_editor() +{ + if (editor) { + editor->hide_all (); + } +} + +void +AudioRegionView::region_renamed () +{ + string str; + + if (region.locked()) { + str += '>'; + str += region.name(); + str += '<'; + } else { + str = region.name(); + } + + if (region.muted()) { + str = string ("!") + str; + } + + set_item_name (region.name(), this); + set_name_text (str); +} + +void +AudioRegionView::region_sync_changed () +{ + int sync_dir; + jack_nframes_t sync_offset; + + sync_offset = region.sync_offset (sync_dir); + + /* this has to handle both a genuine change of position, a change of samples_per_unit, + and a change in the bounds of the region. + */ + + if (sync_offset == 0) { + + /* no sync mark - its the start of the region */ + + gtk_canvas_item_hide (sync_mark); + + } else { + + if ((sync_dir < 0) || ((sync_dir > 0) && (sync_offset > region.length()))) { + + /* no sync mark - its out of the bounds of the region */ + + gtk_canvas_item_hide (sync_mark); + + } else { + + /* lets do it */ + + GtkArg args[1]; + GtkCanvasPoints* points; + + args[0].name = X_("points"); + + gtk_object_getv (GTK_OBJECT(sync_mark), 1, args); + points = static_cast (GTK_VALUE_POINTER(args[0])); + + double offset = sync_offset / samples_per_unit; + + points->coords[0] = offset - ((sync_mark_width-1)/2); + points->coords[1] = 1; + + points->coords[2] = offset + (sync_mark_width-1)/2; + points->coords[3] = 1; + + points->coords[4] = offset; + points->coords[5] = sync_mark_width - 1; + + points->coords[6] = offset - ((sync_mark_width-1)/2); + points->coords[7] = 1; + + gtk_canvas_item_show (sync_mark); + gtk_canvas_item_set (sync_mark, "points", points, NULL); + + gtk_canvas_points_unref (points); + } + } +} + +void +AudioRegionView::set_waveform_visible (bool yn) +{ + if (((_flags & WaveformVisible) != yn)) { + if (yn) { + for (uint32_t n=0; n < waves.size(); ++n) { + gtk_canvas_item_show (waves[n]); + } + _flags |= WaveformVisible; + } else { + for (uint32_t n=0; n < waves.size(); ++n) { + gtk_canvas_item_hide (waves[n]); + } + _flags &= ~WaveformVisible; + } + store_flags (); + } +} + +void +AudioRegionView::temporarily_hide_envelope () +{ + gain_line->hide (); +} + +void +AudioRegionView::unhide_envelope () +{ + if (_flags & EnvelopeVisible) { + gain_line->show (); + } +} + +void +AudioRegionView::set_envelope_visible (bool yn) +{ + if ((_flags & EnvelopeVisible) != yn) { + if (yn) { + gain_line->show (); + _flags |= EnvelopeVisible; + } else { + gain_line->hide (); + _flags &= ~EnvelopeVisible; + } + store_flags (); + } +} + +void +AudioRegionView::create_waves () +{ + bool create_zero_line = true; + + AudioTimeAxisView& atv (*(dynamic_cast(&trackview))); // ick + + if (!atv.get_diskstream()) { + return; + } + + uint32_t nchans = atv.get_diskstream()->n_channels(); + +// if (wait_for_waves) { + /* in tmp_waves, set up null pointers for each channel so the vector is allocated */ + for (uint32_t n = 0; n < nchans; ++n) { + tmp_waves.push_back (0); + } +// } + + for (uint32_t n = 0; n < nchans; ++n) { + + if (n >= region.n_channels()) { + break; + } + + wave_caches.push_back (gtk_canvas_waveview_cache_new ()); + + if (wait_for_waves) { + if (region.source(n).peaks_ready (bind (slot (*this, &AudioRegionView::peaks_ready_handler), n))) { + create_one_wave (n, true); + } else { + create_zero_line = false; + } + } else { + create_one_wave (n, true); + } + } + + if (create_zero_line) { + zero_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_simpleline_get_type(), + "x1", (gdouble) 1.0, + "x2", (gdouble) (region.length() / samples_per_unit) - 1.0, + "color_rgba", (guint) color_map[cZeroLine], + NULL); + manage_zero_line (); + } +} + +void +AudioRegionView::create_one_wave (uint32_t which, bool direct) +{ + AudioTimeAxisView& atv (*(dynamic_cast(&trackview))); // ick + uint32_t nchans = atv.get_diskstream()->n_channels(); + uint32_t n; + uint32_t nwaves = std::min (nchans, region.n_channels()); + + gdouble ht; + if (trackview.height < NAME_HIGHLIGHT_SIZE) { + ht = ((trackview.height) / (double) nchans); + } else { + ht = ((trackview.height - NAME_HIGHLIGHT_SIZE) / (double) nchans); + } + gdouble yoff = which * ht; + + GtkCanvasItem *wave = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_waveview_get_type (), + "data_src", (gpointer) ®ion, + "cache", wave_caches[which], + "cache_updater", (gboolean) true, + "channel", (guint32) which, + "length_function", (gpointer) region_length_from_c, + "sourcefile_length_function",(gpointer) sourcefile_length_from_c, + "peak_function", (gpointer) region_read_peaks_from_c, + "x", 0.0, + "y", yoff, + "height", (double) ht, + "samples_per_unit", samples_per_unit, + "amplitude_above_axis", _amplitude_above_axis, + "wave_color", (guint32) (region.muted() ? color_map[cMutedWaveForm] : color_map[cWaveForm]), + "region_start",(guint32) region.start(), + NULL); + + if (!(_flags & WaveformVisible)) { + gtk_canvas_item_hide (wave); + } + + /* note: calling this function is serialized by the lock + held in the peak building thread that signals that + peaks are ready for use *or* by the fact that it is + called one by one from the GUI thread. + */ + + if (which < nchans) { + tmp_waves[which] = (wave); + } else { + /* n-channel track, >n-channel source */ + } + + /* see if we're all ready */ + + for (n = 0; n < nchans; ++n) { + if (tmp_waves[n] == 0) { + break; + } + } + + if (n == nwaves) { + /* all waves are ready */ + tmp_waves.resize(nwaves); + waves = tmp_waves; + tmp_waves.clear (); + + if (!zero_line) { + zero_line = gtk_canvas_item_new (GTK_CANVAS_GROUP(group), + gtk_canvas_simpleline_get_type(), + "x1", (gdouble) 1.0, + "x2", (gdouble) (region.length() / samples_per_unit) - 1.0, + "color_rgba", (guint) color_map[cZeroLine], + NULL); + manage_zero_line (); + } + } +} + +void +AudioRegionView::peaks_ready_handler (uint32_t which) +{ + Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &AudioRegionView::create_one_wave), which, false)); +} + +void +AudioRegionView::add_gain_point_event (GtkCanvasItem *item, GdkEvent *ev) +{ + double x, y; + + /* don't create points that can't be seen */ + + set_envelope_visible (true); + + x = ev->button.x; + y = ev->button.y; + + gtk_canvas_item_w2i (item, &x, &y); + + jack_nframes_t fx = trackview.editor.pixel_to_frame (x); + + if (fx > region.length()) { + return; + } + + /* compute vertical fractional position */ + + y = 1.0 - (y / (trackview.height - NAME_HIGHLIGHT_SIZE)); + + /* map using gain line */ + + gain_line->view_to_model_y (y); + + trackview.session().begin_reversible_command (_("add gain control point")); + trackview.session().add_undo (region.envelope().get_memento()); + + + if (!region.envelope_active()) { + trackview.session().add_undo( bind( slot(region, &AudioRegion::set_envelope_active), false) ); + region.set_envelope_active(true); + trackview.session().add_redo( bind( slot(region, &AudioRegion::set_envelope_active), true) ); + } + + region.envelope().add (fx, y); + + trackview.session().add_redo_no_execute (region.envelope().get_memento()); + trackview.session().commit_reversible_command (); +} + +void +AudioRegionView::remove_gain_point_event (GtkCanvasItem *item, GdkEvent *ev) +{ + ControlPoint *cp = reinterpret_cast (gtk_object_get_data(GTK_OBJECT(item), "control_point")); + region.envelope().erase (cp->model); +} + +void +AudioRegionView::store_flags() +{ + XMLNode *node = new XMLNode ("GUI"); + + node->add_property ("waveform-visible", (_flags & WaveformVisible) ? "yes" : "no"); + node->add_property ("envelope-visible", (_flags & EnvelopeVisible) ? "yes" : "no"); + + region.add_extra_xml (*node); +} + +void +AudioRegionView::set_flags (XMLNode* node) +{ + XMLProperty *prop; + + if ((prop = node->property ("waveform-visible")) != 0) { + if (prop->value() == "yes") { + _flags |= WaveformVisible; + } + } + + if ((prop = node->property ("envelope-visible")) != 0) { + if (prop->value() == "yes") { + _flags |= EnvelopeVisible; + } + } +} + +void +AudioRegionView::set_waveform_shape (WaveformShape shape) +{ + bool yn; + + /* this slightly odd approach is to leave the door open to + other "shapes" such as spectral displays, etc. + */ + + switch (shape) { + case Rectified: + yn = true; + break; + + default: + yn = false; + break; + } + + if (yn != (bool) (_flags & WaveformRectified)) { + for (vector::iterator wave = waves.begin(); wave != waves.end() ; ++wave) { + gtk_canvas_item_set ((*wave), "rectified", (gboolean) yn, NULL); + } + + if (zero_line) { + if (yn) { + gtk_canvas_item_hide (zero_line); + } else { + gtk_canvas_item_show (zero_line); + } + } + + if (yn) { + _flags |= WaveformRectified; + } else { + _flags &= ~WaveformRectified; + } + } +} + +std::string +AudioRegionView::get_item_name () +{ + return region.name(); +} + +void +AudioRegionView::move (double x_delta, double y_delta) +{ + if (region.locked() || (x_delta == 0 && y_delta == 0)) { + return; + } + + gtk_canvas_item_move (get_canvas_group(), x_delta, y_delta); + + /* note: ghosts never leave their tracks so y_delta for them is always zero */ + + for (vector::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + gtk_canvas_item_move ((*i)->group, x_delta, 0.0); + } +} + +GhostRegion* +AudioRegionView::add_ghost (AutomationTimeAxisView& atv) +{ + AudioTimeAxisView& myatv (*(dynamic_cast(&trackview))); // ick + double unit_position = region.position () / samples_per_unit; + GhostRegion* ghost = new GhostRegion (atv, unit_position); + uint32_t nchans; + + nchans = myatv.get_diskstream()->n_channels(); + + for (uint32_t n = 0; n < nchans; ++n) { + + if (n >= region.n_channels()) { + break; + } + + GtkCanvasItem *wave = gtk_canvas_item_new (GTK_CANVAS_GROUP(ghost->group), + gtk_canvas_waveview_get_type (), + "data_src", (gpointer) ®ion, + "cache", wave_caches[n], + "cache_updater", (gboolean) false, + "channel", (guint32) n, + "length_function", (gpointer) region_length_from_c, + "sourcefile_length_function",(gpointer) sourcefile_length_from_c, + "peak_function", (gpointer) region_read_peaks_from_c, + "x", 0.0, + "samples_per_unit", samples_per_unit, + "amplitude_above_axis", _amplitude_above_axis, + "wave_color", color_map[cGhostTrackWave], + "region_start", (guint32) region.start(), + NULL); + + + ghost->waves.push_back(wave); + } + + ghost->set_height (); + ghost->set_duration (region.length() / samples_per_unit); + ghosts.push_back (ghost); + + ghost->GoingAway.connect (slot (*this, &AudioRegionView::remove_ghost)); + + return ghost; +} + +void +AudioRegionView::remove_ghost (GhostRegion* ghost) +{ + if (in_destructor) { + return; + } + + for (vector::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + if (*i == ghost) { + ghosts.erase (i); + break; + } + } +} + +uint32_t +AudioRegionView::get_fill_color () +{ + return fill_color; +} + +void +AudioRegionView::entered () +{ + if (_flags & EnvelopeVisible) { + gain_line->show_all_control_points (); + } + + uint32_t r,g,b,a; + UINT_TO_RGBA(fade_color,&r,&g,&b,&a); + a=255; + + gtk_canvas_item_set (fade_in_handle, "fill_color_rgba", RGBA_TO_UINT(r,g,b,a), NULL); + gtk_canvas_item_set (fade_out_handle, "fill_color_rgba", RGBA_TO_UINT(r,g,b,a), NULL); +} + +void +AudioRegionView::exited () +{ + gain_line->hide_all_but_selected_control_points (); + + uint32_t r,g,b,a; + UINT_TO_RGBA(fade_color,&r,&g,&b,&a); + a=0; + + gtk_canvas_item_set (fade_in_handle, "fill_color_rgba", RGBA_TO_UINT(r,g,b,a), NULL); + gtk_canvas_item_set (fade_out_handle, "fill_color_rgba", RGBA_TO_UINT(r,g,b,a), NULL); +} + +void +AudioRegionView::envelope_active_changed () +{ + gain_line->set_line_color (region.envelope_active() ? color_map[cGainLine] : color_map[cGainLineInactive]); +} + +void +AudioRegionView::set_waveview_data_src() +{ + + double unit_length= region.length() / samples_per_unit; + + for (uint32_t n = 0; n < waves.size(); ++n) { + // TODO: something else to let it know the channel + gtk_canvas_item_set (waves[n], "data_src", ®ion, NULL); + } + + for (vector::iterator i = ghosts.begin(); i != ghosts.end(); ++i) { + + (*i)->set_duration (unit_length); + + for (vector::iterator w = (*i)->waves.begin(); w != (*i)->waves.end(); ++w) { + gtk_canvas_item_set ((*w), "data_src", ®ion, NULL); + } + } + +} + + diff --git a/gtk2_ardour/regionview.h b/gtk2_ardour/regionview.h new file mode 100644 index 0000000000..0a40622bd0 --- /dev/null +++ b/gtk2_ardour/regionview.h @@ -0,0 +1,187 @@ +/* + Copyright (C) 2001-2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __gtk_ardour_region_view_h__ +#define __gtk_ardour_region_view_h__ + +#include +#include +#include +#include +#include + +#include "time_axis_view_item.h" +#include "automation_line.h" +#include "enums.h" +#include "canvas-waveview.h" + +namespace ARDOUR { + class AudioRegion; + class PeakData; +}; + +class AudioTimeAxisView; +class AudioRegionGainLine; +class AudioRegionEditor; +class GhostRegion; +class AutomationTimeAxisView; + +class AudioRegionView : public TimeAxisViewItem +{ + public: + AudioRegionView (GtkCanvasGroup *, + AudioTimeAxisView&, + ARDOUR::AudioRegion&, + double initial_samples_per_unit, + double amplitude_above_axis, + GdkColor& base_color, + bool wait_for_waves); + ~AudioRegionView (); + + ARDOUR::AudioRegion& region; // ok, let 'em have it + bool is_valid() const { return valid; } + void set_valid (bool yn) { valid = yn; } + + std::string get_item_name(); + void set_height (double); + void set_samples_per_unit (double); + bool set_duration (jack_nframes_t, void*); + + void set_amplitude_above_axis (gdouble spp); + + void move (double xdelta, double ydelta); + + void raise (); + void raise_to_top (); + void lower (); + void lower_to_bottom (); + + bool set_position(jack_nframes_t pos, void* src, double* delta = 0); + + void temporarily_hide_envelope (); // dangerous + void unhide_envelope (); // dangerous + + void set_envelope_visible (bool); + void set_waveform_visible (bool yn); + void set_waveform_shape (WaveformShape); + + bool waveform_rectified() const { return _flags & WaveformRectified; } + bool waveform_visible() const { return _flags & WaveformVisible; } + bool envelope_visible() const { return _flags & EnvelopeVisible; } + + void show_region_editor (); + void hide_region_editor(); + + void add_gain_point_event (GtkCanvasItem *item, GdkEvent *event); + void remove_gain_point_event (GtkCanvasItem *item, GdkEvent *event); + + AudioRegionGainLine* get_gain_line() const { return gain_line; } + + void region_changed (ARDOUR::Change); + void envelope_active_changed (); + + static SigC::Signal1 AudioRegionViewGoingAway; + SigC::Signal0 GoingAway; + + GhostRegion* add_ghost (AutomationTimeAxisView&); + void remove_ghost (GhostRegion*); + + void reset_fade_in_shape_width (jack_nframes_t); + void reset_fade_out_shape_width (jack_nframes_t); + void set_fade_in_active (bool); + void set_fade_out_active (bool); + + uint32_t get_fill_color (); + + virtual void entered (); + virtual void exited (); + + private: + enum Flags { + EnvelopeVisible = 0x1, + WaveformVisible = 0x4, + WaveformRectified = 0x8 + }; + + vector waves; /* waveviews */ + vector tmp_waves; /* see ::create_waves()*/ + GtkCanvasItem* sync_mark; /* polgyon for sync position */ + GtkCanvasItem* no_wave_msg; /* text */ + GtkCanvasItem* zero_line; /* simpleline */ + GtkCanvasItem* fade_in_shape; /* polygon */ + GtkCanvasItem* fade_out_shape; /* polygon */ + GtkCanvasItem* fade_in_handle; /* simplerect */ + GtkCanvasItem* fade_out_handle; /* simplerect */ + + AudioRegionGainLine* gain_line; + AudioRegionEditor *editor; + + vector control_points; + double _amplitude_above_axis; + double current_visible_sync_position; + + uint32_t _flags; + uint32_t fade_color; + bool valid; /* see StreamView::redisplay_diskstream() */ + double _pixel_width; + double _height; + bool in_destructor; + bool wait_for_waves; + + void reset_fade_shapes (); + void reset_fade_in_shape (); + void reset_fade_out_shape (); + void fade_in_changed (); + void fade_out_changed (); + void fade_in_active_changed (); + void fade_out_active_changed (); + + void region_resized (ARDOUR::Change); + void region_moved (void *); + void region_muted (); + void region_locked (); + void region_opacity (); + void region_layered (); + void region_renamed (); + void region_sync_changed (); + void region_scale_amplitude_changed (); + + static gint _lock_toggle (GtkCanvasItem*, GdkEvent*, void*); + void lock_toggle (); + + void create_waves (); + void create_one_wave (uint32_t, bool); + void manage_zero_line (); + void peaks_ready_handler (uint32_t); + void reset_name (gdouble width); + void set_flags (XMLNode *); + void store_flags (); + + void set_colors (); + void compute_colors (GdkColor&); + void set_frame_color (); + void reset_width_dependent_items (double pixel_width); + void set_waveview_data_src(); + + vector wave_caches; + vector ghosts; +}; + +#endif /* __gtk_ardour_region_view_h__ */ diff --git a/gtk2_ardour/rgb_macros.h b/gtk2_ardour/rgb_macros.h new file mode 100644 index 0000000000..f0a67ec0bd --- /dev/null +++ b/gtk2_ardour/rgb_macros.h @@ -0,0 +1,288 @@ +/* + Copyright (C) 2000 EMC Capital Management, Inc. + + Developed by Jon Trowbridge and + Havoc Pennington . + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __gtk_ardour_rgb_macros_h__ +#define __gtk_ardour_rgb_macros_h__ + +/* + Some convenient macros for drawing into an RGB buffer. + Beware of side effects, code-bloat, and all of the other classic + cpp-perils... +*/ + +#define RGB_TO_UINT(r,g,b) ((((guint)(r))<<16)|(((guint)(g))<<8)|((guint)(b))) +#define RGB_TO_RGBA(x,a) (((x) << 8) | ((((guint)a) & 0xff))) +#define RGBA_TO_UINT(r,g,b,a) RGB_TO_RGBA(RGB_TO_UINT(r,g,b), a) +#define RGB_WHITE RGB_TO_UINT(0xff, 0xff, 0xff) +#define RGB_BLACK RGB_TO_UINT(0x00, 0x00, 0x00) +#define RGB_RED RGB_TO_UINT(0xff, 0x00, 0x00) +#define RGB_GREEN RGB_TO_UINT(0x00, 0xff, 0x00) +#define RGB_BLUE RGB_TO_UINT(0x00, 0x00, 0xff) +#define RGB_YELLOW RGB_TO_UINT(0xff, 0xff, 0x00) +#define RGB_VIOLET RGB_TO_UINT(0xff, 0x00, 0xff) +#define RGB_CYAN RGB_TO_UINT(0x00, 0xff, 0xff) +#define RGBA_WHITE RGB_TO_RGBA(RGB_WHITE, 0xff) +#define RGBA_BLACK RGB_TO_RGBA(RGB_BLACK, 0xff) +#define RGBA_RED RGB_TO_RGBA(RGB_RED, 0xff) +#define RGBA_GREEN RGB_TO_RGBA(RGB_GREEN, 0xff) +#define RGBA_BLUE RGB_TO_RGBA(RGB_BLUE, 0xff) +#define RGBA_YELLOW RGB_TO_RGBA(RGB_YELLOW, 0xff) +#define RGBA_VIOLET RGB_TO_RGBA(RGB_VIOLET, 0xff) +#define RGBA_CYAN RGB_TO_RGBA(RGB_CYAN, 0xff) +#define RGB_GREY(x) RGB_TO_UINT(x,x,x) +#define RGBA_GREY(x) RGB_TO_RGBA(RGB_GREY(x), 0xff) +#define UINT_RGBA_R(x) (((guint)(x))>>24) +#define UINT_RGBA_G(x) ((((guint)(x))>>16)&0xff) +#define UINT_RGBA_B(x) ((((guint)(x))>>8)&0xff) +#define UINT_RGBA_A(x) (((guint)(x))&0xff) +#define UINT_RGBA_CHANGE_R(x, r) (((x)&(~(0xff<<24)))|(((r)&0xff)<<24)) +#define UINT_RGBA_CHANGE_G(x, g) (((x)&(~(0xff<<16)))|(((g)&0xff)<<16)) +#define UINT_RGBA_CHANGE_B(x, b) (((x)&(~(0xff<<8)))|(((b)&0xff)<<8)) +#define UINT_RGBA_CHANGE_A(x, a) (((x)&(~0xff))|((a)&0xff)) +#define UINT_TO_RGB(u,r,g,b) \ +{ (*(r)) = ((u)>>16)&0xff; (*(g)) = ((u)>>8)&0xff; (*(b)) = (u)&0xff; } +#define UINT_TO_RGBA(u,r,g,b,a) \ +{ UINT_TO_RGB(((u)>>8),r,g,b); (*(a)) = (u)&0xff; } +#define MONO_INTERPOLATE(v1, v2, t) ((gint)rint((v2)*(t)+(v1)*(1-(t)))) +#define UINT_INTERPOLATE(c1, c2, t) \ + RGBA_TO_UINT( MONO_INTERPOLATE(UINT_RGBA_R(c1), UINT_RGBA_R(c2), t), \ + MONO_INTERPOLATE(UINT_RGBA_G(c1), UINT_RGBA_G(c2), t), \ + MONO_INTERPOLATE(UINT_RGBA_B(c1), UINT_RGBA_B(c2), t), \ + MONO_INTERPOLATE(UINT_RGBA_A(c1), UINT_RGBA_A(c2), t) ) +#define PIXEL_RGB(p, r, g, b) \ +{((guchar*)(p))[0]=(r); ((guchar*)(p))[1]=(g); ((guchar*)(p))[2]=(b);} +#define PIXEL_RGBA(p, r, g, b, a) \ +{ if ((a)>=0xff) { PIXEL_RGB(p,r,g,b) } \ + else if ((a)>0) { \ + guint pixel_tmp; \ + pixel_tmp = ((guchar*)(p))[0]; \ + ((guchar*)(p))[0] = pixel_tmp + ((((r)-pixel_tmp)*(a)+0x80) >> 8); \ + pixel_tmp = ((guchar*)(p))[1]; \ + ((guchar*)(p))[1] = pixel_tmp + ((((g)-pixel_tmp)*(a)+0x80) >> 8); \ + pixel_tmp = ((guchar*)(p))[2]; \ + ((guchar*)(p))[2] = pixel_tmp + ((((b)-pixel_tmp)*(a)+0x80) >> 8); }} +#define PIXEL_RGB_UINT(p, i) \ +UINT_TO_RGB((i), ((guchar*)p), ((guchar*)p)+1, ((guchar*)p)+2) +#define PIXEL_RGBA_UINT(p, i) \ + PIXEL_RGBA((p), ((i)>>24)&0xff, ((i)>>16)&0xff, ((i)>>8)&0xff, (i)&0xff) +#define PIXEL_BLACK(p) PIXEL_RGB(p,0,0,0) +#define PIXEL_WHITE(p) PIXEL_RGB(p,0xff,0xff,0xff) +#define PIXEL_GREY(p,g) PIXEL_RGB(p,g,g,g) +#define PIXEL_GREYA(p,g,a) PIXEL_RGBA(p,g,g,g,a) +#define BUF_PTR(inbuf, ptx, pty) \ + ((inbuf)->buf + 3*((ptx)-(inbuf)->rect.x0) + (inbuf)->buf_rowstride*((pty)-(inbuf)->rect.y0)) +#define BUF_INBOUNDS_X(inbuf, ptx) \ +((inbuf)->rect.x0 <= (ptx) && (ptx) < (inbuf)->rect.x1) +#define BUF_INBOUNDS_Y(inbuf, pty) \ +((inbuf)->rect.y0 <= (pty) && (pty) < (inbuf)->rect.y1) +#define PAINT_DOT(inbuf, colr, colg, colb,ptx, pty) \ +{ \ + guchar* pd_p; \ + if (BUF_INBOUNDS_X(inbuf, ptx) && BUF_INBOUNDS_Y(inbuf, pty)) { \ + pd_p = BUF_PTR(inbuf, ptx, pty); \ + PIXEL_RGB(pd_p, (colr), (colg), (colb)); \ + } \ +} +#define FAST_PAINT_DOT(inbuf, colr, colg, colb,ptx, pty) \ +{ \ + guchar* pd_p; \ + pd_p = BUF_PTR(inbuf, ptx, pty); \ + PIXEL_RGB(pd_p, (colr), (colg), (colb)); \ +} +#define PAINT_DOTA(inbuf, colr, colg, colb, cola, ptx, pty) \ +{ \ + guchar* pd_p; \ + if (BUF_INBOUNDS_X(inbuf, ptx) && BUF_INBOUNDS_Y(inbuf, pty)) { \ + pd_p = BUF_PTR(inbuf, ptx, pty); \ + PIXEL_RGBA(pd_p, (colr), (colg), (colb), (cola)); \ + } \ +} +#define FAST_PAINT_DOTA(inbuf, colr, colg, colb, cola, ptx, pty) \ +{ \ + guchar* pd_p; \ + pd_p = BUF_PTR(inbuf, ptx, pty); \ + PIXEL_RGBA(pd_p, (colr), (colg), (colb), (cola)); \ +} +#define PAINT_HORIZ(inbuf, colr, colg, colb, ptx0, ptx1, pty) \ +{ \ + GtkCanvasBuf* ph_buf = (inbuf); \ + guchar* ph_p; \ + gint ph_a0, ph_a1; \ + gint ph_colr=(colr), ph_colg=(colg), ph_colb=(colb); \ +\ + ph_a0 = MAX(ph_buf->rect.x0, (ptx0)); \ + ph_a1 = MIN(ph_buf->rect.x1, (ptx1)); \ +\ + if (ph_a0 < ph_a1 && BUF_INBOUNDS_Y(ph_buf, pty)) { \ + ph_p = BUF_PTR(ph_buf, ph_a0, pty); \ + while (ph_a0 < ph_a1) { \ + PIXEL_RGB(ph_p, ph_colr, ph_colg, ph_colb); \ + ++ph_a0; \ + ph_p += 3; \ + } \ + } \ +} +#define FAST_PAINT_HORIZ(inbuf, colr, colg, colb, ptx0, ptx1, pty) \ +{ \ + GtkCanvasBuf* ph_buf = (inbuf); \ + guchar* ph_p; \ + gint ph_a0, ph_a1; \ + gint ph_colr=(colr), ph_colg=(colg), ph_colb=(colb); \ +\ + ph_a0 = MAX(ph_buf->rect.x0, (ptx0)); \ + ph_a1 = MIN(ph_buf->rect.x1, (ptx1)); \ +\ + if (ph_a0 < ph_a1 && BUF_INBOUNDS_Y(ph_buf, pty)) { \ + ph_p = BUF_PTR(ph_buf, ph_a0, pty); \ + while (ph_a0 < ph_a1) { \ + PIXEL_RGB(ph_p, ph_colr, ph_colg, ph_colb); \ + ++ph_a0; \ + ph_p += 3; \ + } \ + } \ +} +#define PAINT_HORIZA(inbuf, colr, colg, colb, cola, ptx0, ptx1, pty) \ +{ \ + GtkCanvasBuf* ph_buf = (inbuf); \ + guchar* ph_p; \ + gint ph_a0, ph_a1; \ + gint ph_colr=(colr), ph_colg=(colg), ph_colb=(colb), ph_cola=(cola); \ +\ + ph_a0 = MAX(ph_buf->rect.x0, (ptx0)); \ + ph_a1 = MIN(ph_buf->rect.x1, (ptx1)); \ +\ + if (ph_a0 < ph_a1 && BUF_INBOUNDS_Y(ph_buf, pty)) { \ + ph_p = BUF_PTR(ph_buf, ph_a0, pty); \ + while (ph_a0 < ph_a1) { \ + PIXEL_RGBA(ph_p, ph_colr, ph_colg, ph_colb, ph_cola); \ + ++ph_a0; \ + ph_p += 3; \ + } \ + } \ +} +#define PAINT_VERT(inbuf, colr, colg, colb, ptx, pty0, pty1) \ +{ \ + GtkCanvasBuf* pv_buf = (inbuf); \ + guchar* pv_p; \ + gint pv_b0, pv_b1; \ + gint pv_colr=(colr), pv_colg=(colg), pv_colb=(colb);\ +\ + pv_b0 = MAX(pv_buf->rect.y0, (pty0)); \ + pv_b1 = MIN(pv_buf->rect.y1, (pty1)); \ +\ + if (pv_b0 < pv_b1 && BUF_INBOUNDS_X(pv_buf, ptx)) { \ + pv_p = BUF_PTR(pv_buf, ptx, pv_b0); \ + while (pv_b0 < pv_b1) { \ + PIXEL_RGB(pv_p, pv_colr, pv_colg, pv_colb); \ + ++pv_b0; \ + pv_p += pv_buf->buf_rowstride; \ + } \ + } \ +} +#define FAST_PAINT_VERT(inbuf, colr, colg, colb, ptx, pty0, pty1) \ +{ \ + GtkCanvasBuf* fpv_buf = (inbuf); \ + guchar* fpv_p; \ + gint fpv_b0, fpv_b1; \ +\ + fpv_b0 = MAX(fpv_buf->rect.y0, (pty0)); \ + fpv_b1 = MIN(fpv_buf->rect.y1, (pty1)); \ +\ + fpv_p = BUF_PTR(fpv_buf, ptx, fpv_b0); \ +\ + while (fpv_b0 < fpv_b1) { \ + PIXEL_RGB(fpv_p, colr, colg, colb); \ + ++fpv_b0; \ + fpv_p += fpv_buf->buf_rowstride; \ + } \ +} +#define PAINT_VERTA(inbuf, colr, colg, colb, cola, ptx, pty0, pty1) \ +{ \ + GtkCanvasBuf* pv_buf = (inbuf); \ + guchar* pv_p; \ + gint pv_b0, pv_b1; \ + gint pv_colr=(colr), pv_colg=(colg), pv_colb=(colb), pv_cola=(cola);\ +\ + pv_b0 = MAX(pv_buf->rect.y0, (pty0)); \ + pv_b1 = MIN(pv_buf->rect.y1, (pty1)); \ +\ + if (pv_b0 < pv_b1 && BUF_INBOUNDS_X(pv_buf, ptx)) { \ + pv_p = BUF_PTR(pv_buf, ptx, pv_b0); \ + while (pv_b0 < pv_b1) { \ + PIXEL_RGBA(pv_p, pv_colr, pv_colg, pv_colb, pv_cola); \ + ++pv_b0; \ + pv_p += pv_buf->buf_rowstride; \ + } \ + } \ +} + +/* Paint a solid-colored box into a GtkCanvasBuf (clipping as necessary). + The box contains (ptx0,pty0), but not (ptx1, pty1). + Each macro arg should appear exactly once in the body of the code. */ +#define PAINT_BOX(inbuf, colr, colg, colb, cola, ptx0, pty0, ptx1, pty1) \ +{ \ + GtkCanvasBuf* pb_buf = (inbuf); \ + guchar* pb_p; \ + guchar* pb_pp; \ + gint pb_a0, pb_a1, pb_b0, pb_b1, pb_i, pb_j; \ + gint pb_colr=(colr), pb_colg=(colg), pb_colb=(colb), pb_cola=(cola); \ +\ + pb_a0 = MAX(pb_buf->rect.x0, (ptx0)); \ + pb_a1 = MIN(pb_buf->rect.x1, (ptx1)); \ + pb_b0 = MAX(pb_buf->rect.y0, (pty0)); \ + pb_b1 = MIN(pb_buf->rect.y1, (pty1)); \ +\ + if (pb_a0 < pb_a1 && pb_b0 < pb_b1) { \ + pb_p = BUF_PTR(pb_buf, pb_a0, pb_b0); \ + for (pb_j=pb_b0; pb_jbuf_rowstride; \ + } \ + } \ +} + +/* No bounds checking in this version */ + +#define FAST_PAINT_BOX(inbuf, colr, colg, colb, cola, ptx0, pty0, ptx1, pty1) \ +{ \ + GtkCanvasBuf* pb_buf = (inbuf); \ + guchar* pb_p; \ + guchar* pb_pp; \ + gint pb_i, pb_j; \ +\ + pb_p = BUF_PTR(pb_buf, ptx0, pty0); \ + for (pb_j=pty0; pb_jbuf_rowstride; \ + } \ +} + +#endif /* __gtk_ardour_rgb_macros_h__ */ diff --git a/gtk2_ardour/route_params_ui.cc b/gtk2_ardour/route_params_ui.cc new file mode 100644 index 0000000000..17901e9e7c --- /dev/null +++ b/gtk2_ardour/route_params_ui.cc @@ -0,0 +1,705 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "route_params_ui.h" +#include "keyboard.h" +#include "mixer_strip.h" +#include "plugin_selector.h" +#include "ardour_ui.h" +#include "plugin_ui.h" +#include "io_selector.h" +#include "send_ui.h" +#include "utils.h" +#include "gui_thread.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace Gtk; +using namespace SigC; + +static const gchar *route_display_titles[] = { N_("Tracks/Buses"), 0 }; +static const gchar *pre_display_titles[] = { N_("Pre Redirects"), 0 }; +static const gchar *post_display_titles[] = { N_("Post Redirects"), 0 }; + +RouteParams_UI::RouteParams_UI (AudioEngine& eng) + : ArdourDialog ("track/bus inspector"), + engine (eng), + route_select_list (internationalize(route_display_titles)), + _route(0), + track_menu(0) +{ + pre_redirect_box = 0; + post_redirect_box = 0; + _route = 0; + _pre_redirect = 0; + _post_redirect = 0; + _input_iosel = 0; + _output_iosel = 0; + _active_pre_view = 0; + _active_post_view = 0; + + using namespace Notebook_Helpers; + + input_frame.set_shadow_type(GTK_SHADOW_NONE); + output_frame.set_shadow_type(GTK_SHADOW_NONE); + + notebook.set_show_tabs (true); + notebook.set_show_border (true); + notebook.set_name ("RouteParamNotebook"); + + route_select_list.column_titles_active(); + route_select_list.set_name ("RouteParamsListDisplay"); + route_select_list.set_shadow_type (GTK_SHADOW_IN); + route_select_list.set_selection_mode (GTK_SELECTION_SINGLE); + route_select_list.set_reorderable (false); + route_select_list.set_usize (75, -1); + route_select_scroller.add (route_select_list); + route_select_scroller.set_policy (GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + + route_select_frame.set_name("RouteSelectBaseFrame"); + route_select_frame.set_shadow_type (GTK_SHADOW_IN); + route_select_frame.add(route_select_scroller); + + list_vpacker.pack_start (route_select_frame, true, true); + + notebook.pages().push_back (TabElem (input_frame, _("Inputs"))); + notebook.pages().push_back (TabElem (output_frame, _("Outputs"))); + notebook.pages().push_back (TabElem (pre_redir_hpane, _("Pre-fader Redirects"))); + notebook.pages().push_back (TabElem (post_redir_hpane, _("Post-fader Redirects"))); + + notebook.set_name ("InspectorNotebook"); + + title_label.set_name ("RouteParamsTitleLabel"); + update_title(); + + // changeable area + route_param_frame.set_name("RouteParamsBaseFrame"); + route_param_frame.set_shadow_type (GTK_SHADOW_IN); + + + route_hpacker.pack_start (notebook, true, true); + + + route_vpacker.pack_start (title_label, false, false); + route_vpacker.pack_start (route_hpacker, true, true); + + + list_hpane.add1 (list_vpacker); + list_hpane.add2 (route_vpacker); + + list_hpane.set_position(110); + + pre_redir_hpane.set_position(110); + post_redir_hpane.set_position(110); + + global_vpacker.pack_start (list_hpane, true, true); + + add (global_vpacker); + set_name ("RouteParamsWindow"); + set_default_size (620,370); + set_title (_("ardour: track/bus inspector")); + set_wmclass (_("ardour_route_parameters"), "Ardour"); + + // events + route_select_list.select_row.connect (slot (*this, &RouteParams_UI::route_selected)); + route_select_list.unselect_row.connect (slot (*this, &RouteParams_UI::route_unselected)); + route_select_list.click_column.connect (slot (*this, &RouteParams_UI::show_track_menu)); + + + add_events (GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|GDK_BUTTON_RELEASE_MASK); + + _plugin_selector = new PluginSelector (PluginManager::the_manager()); + _plugin_selector->delete_event.connect (bind (slot (just_hide_it), + static_cast (_plugin_selector))); + + + delete_event.connect (bind (slot (just_hide_it), static_cast (this))); +} + +RouteParams_UI::~RouteParams_UI () +{ +} + +void +RouteParams_UI::add_route (Route* route) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RouteParams_UI::add_route), route)); + + if (route->hidden()) { + return; + } + + const gchar *rowdata[1]; + rowdata[0] = route->name().c_str(); + route_select_list.rows().push_back (rowdata); + route_select_list.rows().back().set_data (route); + //route_select_list.rows().back().select (); + + route->name_changed.connect (bind (slot (*this, &RouteParams_UI::route_name_changed), route)); + route->GoingAway.connect (bind (slot (*this, &RouteParams_UI::route_removed), route)); +} + + +void +RouteParams_UI::route_name_changed (void *src, Route *route) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RouteParams_UI::route_name_changed), src, route)); + + CList_Helpers::RowList::iterator i; + + if ((i = route_select_list.rows().find_data (route)) == route_select_list.rows().end()) { + error << _("route display list item for renamed route not found!") << endmsg; + return; + } + + route_select_list.cell ((*i)->get_row_num(), 0).set_text (route->name()); + + if (route == _route) { + track_input_label.set_text (route->name()); + update_title(); + } +} + +void +RouteParams_UI::setup_redirect_boxes() +{ + if (session && _route) { + + // just in case... shouldn't need this + cleanup_redirect_boxes(); + + // construct new redirect boxes + pre_redirect_box = new RedirectBox(PreFader, *session, *_route, *_plugin_selector, _rr_selection); + post_redirect_box = new RedirectBox(PostFader, *session, *_route, *_plugin_selector, _rr_selection); + + pre_redirect_box->set_title (pre_display_titles[0]); + pre_redirect_box->set_title_shown (true); + post_redirect_box->set_title (post_display_titles[0]); + post_redirect_box->set_title_shown (true); + + pre_redir_hpane.add1 (*pre_redirect_box); + post_redir_hpane.add1 (*post_redirect_box); + + pre_redirect_box->RedirectSelected.connect (bind (slot (*this, &RouteParams_UI::redirect_selected), PreFader)); + pre_redirect_box->RedirectUnselected.connect (bind (slot (*this, &RouteParams_UI::redirect_selected), PreFader)); + post_redirect_box->RedirectSelected.connect (bind (slot (*this, &RouteParams_UI::redirect_selected), PostFader)); + post_redirect_box->RedirectUnselected.connect (bind (slot (*this, &RouteParams_UI::redirect_selected), PostFader)); + + } + +} + +void +RouteParams_UI::cleanup_redirect_boxes() +{ + if (pre_redirect_box) { + pre_redir_hpane.remove(*pre_redirect_box); + delete pre_redirect_box; + pre_redirect_box = 0; + } + + if (post_redirect_box) { + post_redir_hpane.remove(*post_redirect_box); + delete post_redirect_box; + post_redirect_box = 0; + } +} + +void +RouteParams_UI::setup_io_frames() +{ + cleanup_io_frames(); + + // input + _input_iosel = new IOSelector (*session, *_route, true); + _input_iosel->redisplay (); + input_frame.add (*_input_iosel); + input_frame.show_all(); + + // output + _output_iosel = new IOSelector (*session, *_route, false); + _output_iosel->redisplay (); + output_frame.add (*_output_iosel); + output_frame.show_all(); +} + +void +RouteParams_UI::cleanup_io_frames() +{ + if (_input_iosel) { + _input_iosel->Finished (IOSelector::Cancelled); + input_frame.remove(); + delete _input_iosel; + _input_iosel = 0; + } + + if (_output_iosel) { + _output_iosel->Finished (IOSelector::Cancelled); + + output_frame.remove(); + delete _output_iosel; + _output_iosel = 0; + } +} + +void +RouteParams_UI::cleanup_pre_view (bool stopupdate) +{ + if (_active_pre_view) { + PluginUI * plugui = 0; + + if (stopupdate && (plugui = dynamic_cast(_active_pre_view)) != 0) { + plugui->stop_updating (0); + } + + _pre_plugin_conn.disconnect(); + pre_redir_hpane.remove(*_active_pre_view); + delete _active_pre_view; + _active_pre_view = 0; + } +} + +void +RouteParams_UI::cleanup_post_view (bool stopupdate) +{ + if (_active_post_view) { + PluginUI * plugui = 0; + + if (stopupdate && (plugui = dynamic_cast(_active_post_view)) != 0) { + plugui->stop_updating (0); + } + _post_plugin_conn.disconnect(); + post_redir_hpane.remove(*_active_post_view); + delete _active_post_view; + _active_post_view = 0; + } +} + + +void +RouteParams_UI::route_removed (Route *route) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RouteParams_UI::route_removed), route)); + /* + route_select_list.freeze (); + route_select_list.clear (); + session->foreach_route (this, &RouteParams_UI::add_route); + route_select_list.thaw (); + */ + + CList_Helpers::RowList::iterator i; + + if ((i = route_select_list.rows().find_data (route)) == route_select_list.rows().end()) { + // couldn't find route to be deleted + return; + } + + if (route == _route) + { + cleanup_io_frames(); + cleanup_pre_view(); + cleanup_post_view(); + cleanup_redirect_boxes(); + + _route = 0; + _pre_redirect = 0; + _post_redirect = 0; + update_title(); + } + + route_select_list.rows().erase(i); + +} + +void +RouteParams_UI::set_session (Session *sess) +{ + ArdourDialog::set_session (sess); + + route_select_list.freeze (); + route_select_list.clear (); + + if (session) { + session->foreach_route (this, &RouteParams_UI::add_route); + session->going_away.connect (slot (*this, &ArdourDialog::session_gone)); + session->RouteAdded.connect (slot (*this, &RouteParams_UI::add_route)); + start_updating (); + } else { + stop_updating (); + } + + route_select_list.thaw (); + + _plugin_selector->set_session (session); +} + + +void +RouteParams_UI::session_gone () +{ + + route_select_list.clear (); + + cleanup_io_frames(); + cleanup_pre_view(); + cleanup_post_view(); + cleanup_redirect_boxes(); + + _route = 0; + _pre_redirect = 0; + _post_redirect = 0; + update_title(); + + ArdourDialog::session_gone(); + +} + +void +RouteParams_UI::route_selected (gint row, gint col, GdkEvent *ev) +{ + Route *route; + + if ((route = (Route *) route_select_list.get_row_data (row)) != 0) { + + if (_route == route) { + // do nothing + return; + } + + // remove event binding from previously selected + if (_route) { + _route_conn.disconnect(); + _route_ds_conn.disconnect(); + cleanup_redirect_boxes(); + cleanup_pre_view(); + cleanup_post_view(); + cleanup_io_frames(); + } + + // update the other panes with the correct info + _route = route; + //update_routeinfo (route); + + setup_io_frames(); + setup_redirect_boxes(); + + // bind to redirects changed event for this route + _route_conn = route->redirects_changed.connect (slot (*this, &RouteParams_UI::redirects_changed)); + + track_input_label.set_text (_route->name()); + + update_title(); + } +} + +void +RouteParams_UI::route_unselected (gint row, gint col, GdkEvent *ev) +{ + if (_route) { + _route_conn.disconnect(); + + // remove from view + cleanup_io_frames(); + cleanup_pre_view(); + cleanup_post_view(); + cleanup_redirect_boxes(); + + _route = 0; + _pre_redirect = 0; + _post_redirect = 0; + track_input_label.set_text(_("NO TRACK")); + update_title(); + } +} + +void +RouteParams_UI::redirects_changed (void *src) + +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RouteParams_UI::redirects_changed), src)); + +// pre_redirect_list.freeze (); +// pre_redirect_list.clear (); +// post_redirect_list.freeze (); +// post_redirect_list.clear (); +// if (_route) { +// _route->foreach_redirect (this, &RouteParams_UI::add_redirect_to_display); +// } +// pre_redirect_list.thaw (); +// post_redirect_list.thaw (); + + cleanup_pre_view(); + cleanup_post_view(); + + _pre_redirect = 0; + _post_redirect = 0; + //update_title(); +} + + + +void +RouteParams_UI::show_track_menu (gint arg) +{ + using namespace Menu_Helpers; + + if (track_menu == 0) { + track_menu = new Menu; + track_menu->set_name ("ArdourContextMenu"); + track_menu->items().push_back + (MenuElem (_("Add Track/Bus"), + slot (*(ARDOUR_UI::instance()), &ARDOUR_UI::add_route))); + } + track_menu->popup (1, 0); +} + + + +void +RouteParams_UI::redirect_selected (ARDOUR::Redirect *redirect, ARDOUR::Placement place) +{ + Insert *insert; + + if ((place == PreFader && _pre_redirect == redirect) + || (place == PostFader && _post_redirect == redirect)){ + return; + } + + if ((insert = dynamic_cast (redirect)) == 0) { + + Send *send; + + if ((send = dynamic_cast (redirect)) != 0) { + + /* its a send */ + + SendUI *send_ui = new SendUI (*send, *session); + + if (place == PreFader) { + cleanup_pre_view(); + _pre_plugin_conn = send->GoingAway.connect (slot (*this, &RouteParams_UI::redirect_going_away)); + _active_pre_view = send_ui; + + pre_redir_hpane.add2 (*_active_pre_view); + pre_redir_hpane.show_all(); + } + else { + cleanup_post_view(); + _post_plugin_conn = send->GoingAway.connect (slot (*this, &RouteParams_UI::redirect_going_away)); + _active_post_view = send_ui; + + post_redir_hpane.add2 (*_active_post_view); + post_redir_hpane.show_all(); + } + } + + } else { + /* its an insert, though we don't know what kind yet. */ + + PluginInsert *plugin_insert; + PortInsert *port_insert; + + if ((plugin_insert = dynamic_cast (insert)) != 0) { + + PluginUI *plugin_ui = new PluginUI (session->engine(), *plugin_insert, true); + + if (place == PreFader) { + cleanup_pre_view(); + _pre_plugin_conn = plugin_insert->plugin().GoingAway.connect (bind (slot (*this, &RouteParams_UI::plugin_going_away), PreFader)); + plugin_ui->start_updating (0); + _active_pre_view = plugin_ui; + pre_redir_hpane.add2 (*_active_pre_view); + pre_redir_hpane.show_all(); + } + else { + cleanup_post_view(); + _post_plugin_conn = plugin_insert->plugin().GoingAway.connect (bind (slot (*this, &RouteParams_UI::plugin_going_away), PostFader)); + plugin_ui->start_updating (0); + _active_post_view = plugin_ui; + post_redir_hpane.add2 (*_active_post_view); + post_redir_hpane.show_all(); + } + + } else if ((port_insert = dynamic_cast (insert)) != 0) { + + PortInsertUI *portinsert_ui = new PortInsertUI (*session, *port_insert); + + if (place == PreFader) { + cleanup_pre_view(); + _pre_plugin_conn = port_insert->GoingAway.connect (slot (*this, &RouteParams_UI::redirect_going_away)); + _active_pre_view = portinsert_ui; + pre_redir_hpane.add2 (*_active_pre_view); + portinsert_ui->redisplay(); + pre_redir_hpane.show_all(); + } + else { + cleanup_post_view(); + _post_plugin_conn = port_insert->GoingAway.connect (slot (*this, &RouteParams_UI::redirect_going_away)); + _active_post_view = portinsert_ui; + post_redir_hpane.add2 (*_active_post_view); + portinsert_ui->redisplay(); + post_redir_hpane.show_all(); + } + } + + } + + if (place == PreFader) { + _pre_redirect = redirect; + } + else { + _post_redirect = redirect; + } + + update_title(); + +} + +void +RouteParams_UI::redirect_unselected (ARDOUR::Redirect *redirect) +{ + // not called anymore + + if (redirect == _pre_redirect) { + cleanup_pre_view(); + _pre_redirect = 0; + } + else if (redirect == _post_redirect) { + cleanup_post_view(); + _post_redirect = 0; + } +} + + + +void +RouteParams_UI::plugin_going_away (Plugin *plugin, Placement place) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RouteParams_UI::plugin_going_away), plugin, place)); + + // delete the current view without calling finish + + if (place == PreFader) { + cleanup_pre_view (false); + _pre_redirect = 0; + } + else { + cleanup_post_view (false); + _post_redirect = 0; + } +} + +void +RouteParams_UI::redirect_going_away (ARDOUR::Redirect *plugin) + +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RouteParams_UI::redirect_going_away), plugin)); + + printf ("redirect going away\n"); + // delete the current view without calling finish + if (plugin == _pre_redirect) { + cleanup_pre_view (false); + _pre_redirect = 0; + } + else if (plugin == _post_redirect) { + cleanup_post_view (false); + _post_redirect = 0; + } +} + + +void +RouteParams_UI::update_title () +{ + if (_route) { + string title; + title += _route->name(); +// title += ": "; + +// if (_redirect && (_current_view == PLUGIN_CONFIG_VIEW || _current_view == SEND_CONFIG_VIEW)) { +// title += _redirect->name(); +// } +// else if (_current_view == INPUT_CONFIG_VIEW) { +// title += _("INPUT"); +// } +// else if (_current_view == OUTPUT_CONFIG_VIEW) { +// title += _("OUTPUT"); +// } + + title_label.set_text(title); + + title = _("ardour: track/bus inspector: ") + title; + set_title(title); + } + else { + title_label.set_text(_("No Route Selected")); + set_title(_("ardour: track/bus/inspector: no route selected")); + } +} + + +void +RouteParams_UI::start_updating () +{ + update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect + (slot (*this, &RouteParams_UI::update_views)); +} + +void +RouteParams_UI::stop_updating () +{ + update_connection.disconnect(); +} + +void +RouteParams_UI::update_views () +{ + SendUI *sui; + // TODO: only do it if correct tab is showing + + if ((sui = dynamic_cast (_active_pre_view)) != 0) { + sui->update (); + } + if ((sui = dynamic_cast (_active_post_view)) != 0) { + sui->update (); + } + +} diff --git a/gtk2_ardour/route_params_ui.h b/gtk2_ardour/route_params_ui.h new file mode 100644 index 0000000000..deaac6f279 --- /dev/null +++ b/gtk2_ardour/route_params_ui.h @@ -0,0 +1,184 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_route_params_ui_h__ +#define __ardour_route_params_ui_h__ + +#include + +#include + +#include +#include +#include +#include + +#include "io_selector.h" +#include "ardour_dialog.h" +#include "keyboard_target.h" +#include "redirect_box.h" +#include "route_redirect_selection.h" + +namespace ARDOUR { + class Route; + class Send; + class Insert; + class Session; + class PortInsert; + class Connection; + class Plugin; +} + +class PluginSelector; + +class RouteParams_UI : public ArdourDialog +{ + public: + RouteParams_UI (ARDOUR::AudioEngine&); + ~RouteParams_UI(); + + void set_session (ARDOUR::Session *); + void session_gone (); + PluginSelector& plugin_selector() { return *_plugin_selector; } + + private: + ARDOUR::AudioEngine& engine; + + Gtk::HBox global_hpacker; + Gtk::VBox global_vpacker; + Gtk::ScrolledWindow scroller; + Gtk::EventBox scroller_base; + Gtk::HBox scroller_hpacker; + Gtk::VBox mixer_scroller_vpacker; + + Gtk::VBox list_vpacker; + Gtk::CList route_select_list; + Gtk::Label route_list_button_label; + Gtk::Button route_list_button; + Gtk::ScrolledWindow route_select_scroller; + + Gtk::Notebook notebook; + Gtk::Frame input_frame; + Gtk::Frame output_frame; + Gtk::HPaned pre_redir_hpane; + Gtk::HPaned post_redir_hpane; + + Gtk::Frame route_select_frame; + + Gtk::HBox route_hpacker; + Gtk::VBox route_vpacker; + + RedirectBox * pre_redirect_box; + RedirectBox * post_redirect_box; + + Gtk::HPaned list_hpane; + + Gtk::HPaned right_hpane; + + Gtk::Frame route_choice_frame; + + Gtk::Frame route_param_frame; + + Gtk::VBox choice_vpacker; + + + Gtk::ToggleButton input_button; + Gtk::ToggleButton output_button; + Gtk::Label track_input_label; + + Gtk::Label title_label; + + Gtk::Container * _active_pre_view; + Gtk::Container * _active_post_view; + IOSelector * _input_iosel; + IOSelector * _output_iosel; + + PluginSelector *_plugin_selector; + RouteRedirectSelection _rr_selection; + + ARDOUR::Route *_route; + SigC::Connection _route_conn; + SigC::Connection _route_ds_conn; + + ARDOUR::Redirect * _pre_redirect; + SigC::Connection _pre_plugin_conn; + + ARDOUR::Redirect * _post_redirect; + SigC::Connection _post_plugin_conn; + + + enum ConfigView { + NO_CONFIG_VIEW = 0, + INPUT_CONFIG_VIEW, + OUTPUT_CONFIG_VIEW, + PLUGIN_CONFIG_VIEW, + PORTINSERT_CONFIG_VIEW, + SEND_CONFIG_VIEW + }; + + ConfigView _current_view; + + void add_route (ARDOUR::Route*); + + void route_name_changed (void *src, ARDOUR::Route *route); + void route_removed (ARDOUR::Route *route); + + + void route_selected (gint row, gint col, GdkEvent *ev); + void route_unselected (gint row, gint col, GdkEvent *ev); + + void setup_io_frames(); + void cleanup_io_frames(); + void cleanup_pre_view(bool stopupdate = true); + void cleanup_post_view(bool stopupdate = true); + + + + void redirects_changed (void *src); + + void setup_redirect_boxes(); + void cleanup_redirect_boxes(); + + void redirect_selected (ARDOUR::Redirect *, ARDOUR::Placement); + void redirect_unselected (ARDOUR::Redirect *); + + void plugin_going_away (ARDOUR::Plugin *foo, ARDOUR::Placement); + void redirect_going_away (ARDOUR::Redirect *foo); + + gint edit_input_configuration (GdkEventButton *ev); + gint edit_output_configuration (GdkEventButton *ev); + + void update_routeinfo (ARDOUR::Route * route); + + Gtk::Menu *track_menu; + void show_track_menu(gint arg); + + void update_title (); + //void unselect_all_redirects (); + + SigC::Connection update_connection; + void update_views (); + + void start_updating (); + void stop_updating (); +}; + + +#endif /* __ardour_route_params_ui_h__ */ diff --git a/gtk2_ardour/route_redirect_selection.cc b/gtk2_ardour/route_redirect_selection.cc new file mode 100644 index 0000000000..730f3317fe --- /dev/null +++ b/gtk2_ardour/route_redirect_selection.cc @@ -0,0 +1,183 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include +#include +#include + +#include "route_redirect_selection.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace SigC; + +RouteRedirectSelection& +RouteRedirectSelection::operator= (const RouteRedirectSelection& other) +{ + if (&other != this) { + redirects = other.redirects; + routes = other.routes; + } + return *this; +} + +bool +operator== (const RouteRedirectSelection& a, const RouteRedirectSelection& b) +{ + return a.redirects == b.redirects && + a.routes == b.routes; +} + +void +RouteRedirectSelection::clear () +{ + clear_redirects (); + clear_routes (); +} + +void +RouteRedirectSelection::clear_redirects () +{ + for (RedirectSelection::iterator i = redirects.begin(); i != redirects.end(); ) { + RedirectSelection::iterator tmp; + + tmp = i; + ++tmp; + + delete *i; + + i = tmp; + } + + redirects.clear (); + RedirectsChanged (); +} + +void +RouteRedirectSelection::clear_routes () +{ + routes.clear (); + RoutesChanged (); +} + +void +RouteRedirectSelection::add (Redirect* r) +{ + if (find (redirects.begin(), redirects.end(), r) == redirects.end()) { + redirects.push_back (r); + + void (RouteRedirectSelection::*pmf)(Redirect*) = &RouteRedirectSelection::remove; + r->GoingAway.connect (slot (*this, pmf)); + + RedirectsChanged(); + } +} + +void +RouteRedirectSelection::add (const vector& rlist) +{ + bool changed = false; + + for (vector::const_iterator i = rlist.begin(); i != rlist.end(); ++i) { + if (find (redirects.begin(), redirects.end(), *i) == redirects.end()) { + redirects.push_back (*i); + + void (RouteRedirectSelection::*pmf)(Redirect*) = &RouteRedirectSelection::remove; + (*i)->GoingAway.connect (slot (*this, pmf)); + changed = true; + } + } + + if (changed) { + RedirectsChanged(); + } +} + +void +RouteRedirectSelection::remove (Redirect* r) +{ + list::iterator i; + if ((i = find (redirects.begin(), redirects.end(), r)) != redirects.end()) { + redirects.erase (i); + RedirectsChanged (); + } +} + +void +RouteRedirectSelection::set (Redirect *r) +{ + clear_redirects (); + add (r); +} + +void +RouteRedirectSelection::set (const vector& rlist) +{ + clear_redirects (); + add (rlist); +} + +void +RouteRedirectSelection::add (Route* r) +{ + if (find (routes.begin(), routes.end(), r) == routes.end()) { + routes.push_back (r); + + void (RouteRedirectSelection::*pmf)(Route*) = &RouteRedirectSelection::remove; + r->GoingAway.connect (bind (slot (*this, pmf), r)); + + RoutesChanged(); + } +} + +void +RouteRedirectSelection::remove (Route* r) +{ + list::iterator i; + if ((i = find (routes.begin(), routes.end(), r)) != routes.end()) { + routes.erase (i); + RoutesChanged (); + } +} + +void +RouteRedirectSelection::set (Route *r) +{ + clear_routes (); + add (r); +} + +bool +RouteRedirectSelection::selected (Route* ms) +{ + return find (routes.begin(), routes.end(), ms) != routes.end(); +} + +bool +RouteRedirectSelection::empty () +{ + return redirects.empty () && routes.empty (); +} + diff --git a/gtk2_ardour/route_redirect_selection.h b/gtk2_ardour/route_redirect_selection.h new file mode 100644 index 0000000000..33aa44aaa2 --- /dev/null +++ b/gtk2_ardour/route_redirect_selection.h @@ -0,0 +1,64 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_route_redirect_selection_h__ +#define __ardour_gtk_route_redirect_selection_h__ + +#include +#include + +#include "redirect_selection.h" +#include "route_selection.h" + +class RouteRedirectSelection : public SigC::Object +{ + public: + RedirectSelection redirects; + RouteSelection routes; + + RouteRedirectSelection() {} + + RouteRedirectSelection& operator= (const RouteRedirectSelection& other); + + SigC::Signal0 RedirectsChanged; + SigC::Signal0 RoutesChanged; + + void clear (); + bool empty(); + + void set (ARDOUR::Redirect*); + void set (const std::vector&); + void add (ARDOUR::Redirect*); + void add (const std::vector&); + void remove (ARDOUR::Redirect*); + + void set (ARDOUR::Route*); + void add (ARDOUR::Route*); + void remove (ARDOUR::Route*); + + void clear_redirects (); + void clear_routes (); + + bool selected (ARDOUR::Route*); +}; + +bool operator==(const RouteRedirectSelection& a, const RouteRedirectSelection& b); + +#endif /* __ardour_gtk_route_redirect_selection_h__ */ diff --git a/gtk2_ardour/route_selection.h b/gtk2_ardour/route_selection.h new file mode 100644 index 0000000000..50797deed3 --- /dev/null +++ b/gtk2_ardour/route_selection.h @@ -0,0 +1,12 @@ +#ifndef __ardour_gtk_route_selection_h__ +#define __ardour_gtk_route_selection_h__ + +#include + +namespace ARDOUR { + class Route; +} + +struct RouteSelection : list {}; + +#endif /* __ardour_gtk_route_selection_h__ */ diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc new file mode 100644 index 0000000000..bd9c535ecd --- /dev/null +++ b/gtk2_ardour/route_ui.cc @@ -0,0 +1,852 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include + +#include + +#include "route_ui.h" +#include "keyboard.h" +#include "utils.h" +#include "prompter.h" +#include "gui_thread.h" + +#include +#include +#include + +#include "i18n.h" + +using namespace SigC; +using namespace Gtk; +using namespace Gtkmmext; +using namespace ARDOUR; + + +RouteUI::RouteUI (ARDOUR::Route& rt, ARDOUR::Session& sess, const char* m_name, + const char* s_name, const char* r_name) + : AxisView(sess), + _route(rt), + mute_button(0), + solo_button(0), + rec_enable_button(0) +{ + xml_node = 0; + mute_menu = 0; + solo_menu = 0; + ignore_toggle = false; + wait_for_release = false; + route_active_menu_item = 0; + + if (set_color_from_route()) { + set_color (unique_random_color()); + } + + _route.GoingAway.connect (slot (*this, &RouteUI::route_removed)); + _route.active_changed.connect (slot (*this, &RouteUI::route_active_changed)); + + mute_button = manage (new BindableToggleButton (& _route.midi_mute_control(), m_name )); + mute_button->set_bind_button_state (2, GDK_CONTROL_MASK); + solo_button = manage (new BindableToggleButton (& _route.midi_solo_control(), s_name )); + solo_button->set_bind_button_state (2, GDK_CONTROL_MASK); + + if (is_audio_track()) { + AudioTrack* at = dynamic_cast(&_route); + + get_diskstream()->record_enable_changed.connect (slot (*this, &RouteUI::route_rec_enable_changed)); + + _session.RecordEnabled.connect (slot (*this, &RouteUI::session_rec_enable_changed)); + _session.RecordDisabled.connect (slot (*this, &RouteUI::session_rec_enable_changed)); + + rec_enable_button = manage (new BindableToggleButton (& at->midi_rec_enable_control(), r_name )); + rec_enable_button->set_bind_button_state (2, GDK_CONTROL_MASK); + + } else { + rec_enable_button = manage (new BindableToggleButton (0, r_name )); + } + + mute_button->unset_flags (GTK_CAN_FOCUS); + solo_button->unset_flags (GTK_CAN_FOCUS); + rec_enable_button->unset_flags (GTK_CAN_FOCUS); + + /* map the current state */ + + update_rec_display (); + map_frozen (); +} + +RouteUI::~RouteUI() +{ + delete mute_menu; +} + +gint +RouteUI::mute_press(GdkEventButton* ev) +{ + if (!ignore_toggle) { + + if (Keyboard::is_context_menu_event (ev)) { + + if (mute_menu == 0){ + build_mute_menu(); + } + + mute_menu->popup(0,0); + + } else { + + if (ev->button == 2) { + // ctrl-button2 click is the midi binding click + // button2-click is "momentary" + + if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) { + wait_for_release = true; + } + } + + if (ev->button == 1 || ev->button == 2) { + + if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) { + + /* ctrl-shift-click applies change to all routes */ + + _session.begin_reversible_command (_("mute change")); + _session.add_undo (_session.global_mute_memento(this)); + _session.set_all_mute (!_route.muted()); + _session.add_redo_no_execute (_session.global_mute_memento(this)); + _session.commit_reversible_command (); + + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + + /* ctrl-click applies change to the mix group. + ctrl-button2 is MIDI learn. + */ + + if (ev->button == 1) { + set_mix_group_mute (_route, !_route.muted()); + } + + } else { + + /* plain click applies change to this route */ + + reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route.muted(), this); + } + } + } + + } + + return stop_signal (*mute_button, "button-press-event"); +} + +gint +RouteUI::mute_release(GdkEventButton* ev) +{ + if (!ignore_toggle) { + if (wait_for_release){ + wait_for_release = false; + // undo the last op + // because the press was the last undoable thing we did + _session.undo (1U); + stop_signal (*mute_button, "button-release-event"); + } + } + return TRUE; +} + +gint +RouteUI::solo_press(GdkEventButton* ev) +{ + if (!ignore_toggle) { + + if (Keyboard::is_context_menu_event (ev)) { + + if (solo_menu == 0) { + build_solo_menu (); + } + + solo_menu->popup (1, 0); + + } else { + + if (ev->button == 2) { + + // ctrl-button2 click is the midi binding click + // button2-click is "momentary" + + if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) { + wait_for_release = true; + } + } + + if (ev->button == 1 || ev->button == 2) { + + if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) { + + /* ctrl-shift-click applies change to all routes */ + + _session.begin_reversible_command (_("solo change")); + _session.add_undo (_session.global_solo_memento(this)); + _session.set_all_solo (!_route.soloed()); + _session.add_redo_no_execute (_session.global_solo_memento(this)); + _session.commit_reversible_command (); + + } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) { + + // ctrl-alt-click: exclusively solo this track, not a toggle */ + + _session.begin_reversible_command (_("solo change")); + _session.add_undo (_session.global_solo_memento(this)); + _session.set_all_solo (false); + _route.set_solo (true, this); + _session.add_redo_no_execute (_session.global_solo_memento(this)); + _session.commit_reversible_command (); + + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) { + + // shift-click: set this route to solo safe + + _route.set_solo_safe (!_route.solo_safe(), this); + wait_for_release = false; + + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + + /* ctrl-click: solo mix group. + ctrl-button2 is MIDI learn. + */ + + if (ev->button == 1) { + set_mix_group_solo (_route, !_route.soloed()); + } + + } else { + + /* click: solo this route */ + + reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route.soloed(), this); + } + } + } + } + + return stop_signal (*solo_button, "button-press-event"); +} + +gint +RouteUI::solo_release(GdkEventButton* ev) +{ + if(!ignore_toggle){ + if (wait_for_release){ + wait_for_release = false; + // undo the last op + // because the press was the last undoable thing we did + + _session.undo (1U); + + stop_signal (*solo_button, "button-release-event"); + } + } + return TRUE; +} + +gint +RouteUI::rec_enable_press(GdkEventButton* ev) +{ + if (!ignore_toggle && is_audio_track()) { + + if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + // do nothing on midi bind event + } + else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) { + + _session.begin_reversible_command (_("rec-enable change")); + _session.add_undo (_session.global_record_enable_memento(this)); + + if (rec_enable_button->get_active()) { + _session.record_disenable_all (); + } else { + _session.record_enable_all (); + } + + _session.add_redo_no_execute (_session.global_record_enable_memento(this)); + _session.commit_reversible_command (); + + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + + set_mix_group_rec_enable (_route, !_route.record_enabled()); + + } else { + + reversibly_apply_audio_track_boolean ("rec-enable change", &AudioTrack::set_record_enable, !audio_track()->record_enabled(), this); + + ignore_toggle = true; + rec_enable_button->set_active(audio_track()->record_enabled()); + ignore_toggle = false; + } + + stop_signal (*rec_enable_button, "button-press-event"); + } + + return TRUE; +} + +void +RouteUI::solo_changed(void* src) +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &RouteUI::update_solo_display)); +} + +void +RouteUI::update_solo_display () +{ + bool x; + + if (solo_button->get_active() != (x = _route.soloed())){ + ignore_toggle = true; + solo_button->set_active(x); + ignore_toggle = false; + } + + /* show solo safe */ + + if (_route.solo_safe()){ + solo_button->set_name(safe_solo_button_name()); + } else { + solo_button->set_name(solo_button_name()); + } +} + +void +RouteUI::mute_changed(void* src) +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &RouteUI::update_mute_display)); +} + +void +RouteUI::update_mute_display () +{ + bool x; + + if (mute_button->get_active() != (x = _route.muted())){ + ignore_toggle = true; + mute_button->set_active(x); + ignore_toggle = false; + } +} + +void +RouteUI::route_rec_enable_changed (void *src) +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &RouteUI::update_rec_display)); +} + +void +RouteUI::session_rec_enable_changed () +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &RouteUI::update_rec_display)); +} + +void +RouteUI::update_rec_display () +{ + bool model = _route.record_enabled(); + bool view = rec_enable_button->get_active(); + + /* first make sure the button's "depressed" visual + is correct. + */ + + if (model != view) { + ignore_toggle = true; + rec_enable_button->set_active (model); + ignore_toggle = false; + } + + /* now make sure its color state is correct */ + + if (model) { + + switch (_session.record_status ()) { + case Session::Disabled: + case Session::Enabled: + if (rec_enable_button->get_state() != GTK_STATE_ACTIVE) { + rec_enable_button->set_state (GTK_STATE_ACTIVE); + } + break; + + case Session::Recording: + if (rec_enable_button->get_state() != GTK_STATE_SELECTED) { + rec_enable_button->set_state (GTK_STATE_SELECTED); + } + break; + } + + } else { + if (rec_enable_button->get_state() != GTK_STATE_NORMAL) { + rec_enable_button->set_state (GTK_STATE_NORMAL); + } + } +} + +void +RouteUI::build_solo_menu (void) +{ + using namespace Menu_Helpers; + + solo_menu = new Menu; + solo_menu->set_name ("ArdourContextMenu"); + MenuList& items = solo_menu->items(); + CheckMenuItem* check; + + check = new CheckMenuItem(_("Solo-safe")); + check->set_active (_route.solo_safe()); + check->toggled.connect (bind (slot (*this, &RouteUI::toggle_solo_safe), check)); + _route.solo_safe_changed.connect(bind (slot (*this, &RouteUI::solo_safe_toggle), check)); + items.push_back (CheckMenuElem(*check)); + check->show_all(); + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("MIDI Bind"), slot (*mute_button, &BindableToggleButton::midi_learn))); + +} + +void +RouteUI::build_mute_menu(void) +{ + using namespace Menu_Helpers; + + mute_menu = new Menu; + mute_menu->set_name ("ArdourContextMenu"); + MenuList& items = mute_menu->items(); + CheckMenuItem* check; + + check = new CheckMenuItem(_("Pre Fader")); + init_mute_menu(PRE_FADER, check); + check->toggled.connect(bind (slot (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check)); + _route.pre_fader_changed.connect(bind (slot (*this, &RouteUI::pre_fader_toggle), check)); + items.push_back (CheckMenuElem(*check)); + check->show_all(); + + check = new CheckMenuItem(_("Post Fader")); + init_mute_menu(POST_FADER, check); + check->toggled.connect(bind (slot (*this, &RouteUI::toggle_mute_menu), POST_FADER, check)); + _route.post_fader_changed.connect(bind (slot (*this, &RouteUI::post_fader_toggle), check)); + items.push_back (CheckMenuElem(*check)); + check->show_all(); + + check = new CheckMenuItem(_("Control Outs")); + init_mute_menu(CONTROL_OUTS, check); + check->toggled.connect(bind (slot (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check)); + _route.control_outs_changed.connect(bind (slot (*this, &RouteUI::control_outs_toggle), check)); + items.push_back (CheckMenuElem(*check)); + check->show_all(); + + check = new CheckMenuItem(_("Main Outs")); + init_mute_menu(MAIN_OUTS, check); + check->toggled.connect(bind (slot (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check)); + _route.main_outs_changed.connect(bind (slot (*this, &RouteUI::main_outs_toggle), check)); + items.push_back (CheckMenuElem(*check)); + check->show_all(); + + items.push_back (SeparatorElem()); + items.push_back (MenuElem (_("MIDI Bind"), slot (*mute_button, &BindableToggleButton::midi_learn))); +} + +void +RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check) +{ + if (_route.get_mute_config (type)) { + check->set_active (true); + } +} + +void +RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check) +{ + _route.set_mute_config(type, check->get_active(), this); +} + +void +RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check) +{ + _route.set_solo_safe (check->get_active(), this); +} + +void +RouteUI::set_mix_group_solo(Route& route, bool yn) +{ + RouteGroup* mix_group; + + if((mix_group = route.mix_group()) != 0){ + _session.begin_reversible_command (_("mix group solo change")); + _session.add_undo (_session.global_solo_memento (this)); + mix_group->apply(&Route::set_solo, yn, this); + _session.add_redo_no_execute (_session.global_solo_memento(this)); + _session.commit_reversible_command (); + } else { + reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route.soloed(), this); + } +} + +void +RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg) +{ + _session.begin_reversible_command (name); + _session.add_undo (bind (slot (_route, func), !yn, (void *) arg)); + _session.add_redo (bind (slot (_route, func), yn, (void *) arg)); + _session.commit_reversible_command (); +} + +void +RouteUI::reversibly_apply_audio_track_boolean (string name, void (AudioTrack::*func)(bool, void *), bool yn, void *arg) +{ + _session.begin_reversible_command (name); + _session.add_undo (bind (slot (*audio_track(), func), !yn, (void *) arg)); + _session.add_redo (bind (slot (*audio_track(), func), yn, (void *) arg)); + _session.commit_reversible_command (); +} + +void +RouteUI::set_mix_group_mute(Route& route, bool yn) +{ + RouteGroup* mix_group; + + if((mix_group = route.mix_group()) != 0){ + _session.begin_reversible_command (_("mix group mute change")); + _session.add_undo (_session.global_mute_memento (this)); + mix_group->apply(&Route::set_mute, yn, this); + _session.add_redo_no_execute (_session.global_mute_memento(this)); + _session.commit_reversible_command (); + } else { + reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route.muted(), this); + } +} + +void +RouteUI::set_mix_group_rec_enable(Route& route, bool yn) +{ + RouteGroup* mix_group; + + if((mix_group = route.mix_group()) != 0){ + _session.begin_reversible_command (_("mix group rec-enable change")); + _session.add_undo (_session.global_record_enable_memento (this)); + mix_group->apply (&Route::set_record_enable, yn, this); + _session.add_redo_no_execute (_session.global_record_enable_memento(this)); + _session.commit_reversible_command (); + } else { + reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route.record_enabled(), this); + } +} + + +bool +RouteUI::choose_color() +{ + bool picked; + GdkColor color; + gdouble current[4]; + + current[0] = _color.get_red() / 65535.0; + current[1] = _color.get_green() / 65535.0; + current[2] = _color.get_blue() / 65535.0; + current[3] = 1.0; + + color = Gtkmmext::UI::instance()->get_color (_("ardour: color selection"), picked, current); + + if (picked) { + set_color (color); + } + + return picked; +} + +void +RouteUI::set_color (Gdk_Color c) +{ + char buf[64]; + + _color = c; + + ensure_xml_node (); + snprintf (buf, sizeof (buf), "%d:%d:%d", c.red, c.green, c.blue); + xml_node->add_property ("color", buf); + + _route.gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */ +} + + +void +RouteUI::ensure_xml_node () +{ + if (xml_node == 0) { + if ((xml_node = _route.extra_xml ("GUI")) == 0) { + xml_node = new XMLNode ("GUI"); + _route.add_extra_xml (*xml_node); + } + } +} + +XMLNode* +RouteUI::get_child_xml_node (string childname) +{ + XMLNode* child; + + ensure_xml_node (); + + + if ((child = find_named_node (*xml_node, childname)) == 0) { + child = new XMLNode (childname); + xml_node->add_child_nocopy (*child); + } + + return child; +} + +int +RouteUI::set_color_from_route () +{ + XMLProperty *prop; + + RouteUI::ensure_xml_node (); + + if ((prop = xml_node->property ("color")) != 0) { + int r, g, b; + sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b); + _color.red = r; + _color.green = g; + _color.blue = b; + return 0; + } + return 1; +} + +void +RouteUI::remove_this_route () +{ + vector choices; + string prompt; + + if (is_audio_track()) { + prompt = compose (_("Do you really want to remove track \"%1\" ?\nYou may also lose the playlist used by this track.\n(cannot be undone)"), _route.name()); + } else { + prompt = compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route.name()); + } + + choices.push_back (_("Yes, remove it.")); + choices.push_back (_("No, do nothing.")); + + Choice prompter (prompt, choices); + + prompter.chosen.connect (Gtk::Main::quit.slot()); + prompter.show_all (); + + Gtk::Main::run (); + + if (prompter.get_choice() == 0) { + Main::idle.connect (bind (slot (&RouteUI::idle_remove_this_route), this)); + } +} + +gint +RouteUI::idle_remove_this_route (RouteUI *rui) +{ + rui->_session.remove_route (rui->_route); + return FALSE; +} + +void +RouteUI::route_removed () +{ + ENSURE_GUI_THREAD(slot (*this, &RouteUI::route_removed)); + + delete this; +} + +void +RouteUI::route_rename () +{ + ArdourPrompter name_prompter (true); + name_prompter.set_prompt (_("new name: ")); + name_prompter.set_initial_text (_route.name()); + name_prompter.done.connect (Gtk::Main::quit.slot()); + name_prompter.show_all (); + + Gtk::Main::run(); + + if (name_prompter.status == Gtkmmext::Prompter::cancelled) { + return; + } + + string result; + name_prompter.get_result (result); + + if (result.length() == 0) { + return; + } + + strip_whitespace_edges (result); + _route.set_name (result, this); +} + +void +RouteUI::name_changed (void *src) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RouteUI::name_changed), src)); + + name_label.set_text (_route.name()); +} + +void +RouteUI::toggle_route_active () +{ + bool yn; + + if (route_active_menu_item) { + if (route_active_menu_item->get_active() != (yn = _route.active())) { + _route.set_active (!yn); + } + } +} + +void +RouteUI::route_active_changed () +{ + if (route_active_menu_item) { + Gtkmmext::UI::instance()->call_slot (bind (slot (*route_active_menu_item, &CheckMenuItem::set_active), _route.active())); + } +} + +void +RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check) +{ + bool yn = _route.solo_safe (); + + if (check->get_active() != yn) { + check->set_active (yn); + } +} +void +RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RouteUI::pre_fader_toggle), src, check)); + + bool yn = _route.get_mute_config(PRE_FADER); + if (check->get_active() != yn) { + check->set_active (yn); + } +} + +void +RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RouteUI::post_fader_toggle), src, check)); + + bool yn = _route.get_mute_config(POST_FADER); + if (check->get_active() != yn) { + check->set_active (yn); + } +} + +void +RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RouteUI::control_outs_toggle), src, check)); + + bool yn = _route.get_mute_config(CONTROL_OUTS); + if (check->get_active() != yn) { + check->set_active (yn); + } +} + +void +RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &RouteUI::main_outs_toggle), src, check)); + + bool yn = _route.get_mute_config(MAIN_OUTS); + if (check->get_active() != yn) { + check->set_active (yn); + } +} + +void +RouteUI::disconnect_input () +{ + _route.disconnect_inputs (this); +} + +void +RouteUI::disconnect_output () +{ + _route.disconnect_outputs (this); +} + +bool +RouteUI::is_audio_track () const +{ + return dynamic_cast(&_route) != 0; +} + +DiskStream* +RouteUI::get_diskstream () const +{ + AudioTrack *at; + + if ((at = dynamic_cast(&_route)) != 0) { + return &at->disk_stream(); + } else { + return 0; + } +} + +AudioTrack* +RouteUI::audio_track() const +{ + return dynamic_cast(&_route); +} +string +RouteUI::name() const +{ + return _route.name(); +} + +void +RouteUI::map_frozen () +{ + ENSURE_GUI_THREAD (slot (*this, &RouteUI::map_frozen)); + + AudioTrack* at = dynamic_cast(&_route); + + if (at) { + switch (at->freeze_state()) { + case AudioTrack::Frozen: + rec_enable_button->set_sensitive (false); + break; + default: + rec_enable_button->set_sensitive (true); + break; + } + } +} diff --git a/gtk2_ardour/route_ui.h b/gtk2_ardour/route_ui.h new file mode 100644 index 0000000000..acdc084306 --- /dev/null +++ b/gtk2_ardour/route_ui.h @@ -0,0 +1,140 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_route_ui__ +#define __ardour_route_ui__ + +#include + +#include +#include +#include +#include + +#include "axis_view.h" + +namespace Gtkmmext { + class BindableToggleButton; +} + +namespace ARDOUR { + class AudioTrack; +} + +class RouteUI : public virtual AxisView +{ + public: + RouteUI(ARDOUR::Route&, ARDOUR::Session&, const char*, const char*, const char*); + virtual ~RouteUI(); + + bool is_audio_track() const; + ARDOUR::DiskStream* get_diskstream() const; + + ARDOUR::Route& route() const { return _route; } + ARDOUR::AudioTrack* audio_track() const; + + string name() const; + + ARDOUR::Route& _route; + + + void set_color (Gdk_Color c); + bool choose_color (); + + bool ignore_toggle; + bool wait_for_release; + + Gtkmmext::BindableToggleButton * mute_button; + Gtkmmext::BindableToggleButton * solo_button; + Gtkmmext::BindableToggleButton * rec_enable_button; + + virtual string solo_button_name () const { return "SoloButton"; } + virtual string safe_solo_button_name () const { return "SafeSoloButton"; } + + Gtk::Menu* mute_menu; + Gtk::Menu* solo_menu; + + XMLNode *xml_node; + void ensure_xml_node (); + + XMLNode* get_child_xml_node (std::string childname); + + gint mute_press(GdkEventButton*); + gint mute_release(GdkEventButton*); + gint solo_press(GdkEventButton*); + gint solo_release(GdkEventButton*); + gint rec_enable_press(GdkEventButton*); + + void solo_changed(void*); + void mute_changed(void*); + void route_rec_enable_changed(void*); + void session_rec_enable_changed(); + + void build_solo_menu (void); + + void solo_safe_toggle (void*, Gtk::CheckMenuItem*); + void toggle_solo_safe (Gtk::CheckMenuItem*); + + void toggle_mute_menu(ARDOUR::mute_type, Gtk::CheckMenuItem*); + void pre_fader_toggle(void*, Gtk::CheckMenuItem*); + void post_fader_toggle(void*, Gtk::CheckMenuItem*); + void control_outs_toggle(void*, Gtk::CheckMenuItem*); + void main_outs_toggle(void*, Gtk::CheckMenuItem*); + + void build_mute_menu(void); + void init_mute_menu(ARDOUR::mute_type, Gtk::CheckMenuItem*); + + void set_mix_group_solo(ARDOUR::Route&, bool); + void set_mix_group_mute(ARDOUR::Route&, bool); + void set_mix_group_rec_enable(ARDOUR::Route&, bool); + + int set_color_from_route (); + + SigC::Connection blink_connection; + + void rec_enable_button_blink (bool onoff, ARDOUR::DiskStream *, Gtk::Widget *w); + + void remove_this_route (); + static gint idle_remove_this_route (RouteUI *); + + void route_rename(); + + virtual void name_changed (void *src); + void route_removed (); + + static gint okay_gplusplus_cannot_do_complex_templates (RouteUI *rui); + + Gtk::CheckMenuItem *route_active_menu_item; + void toggle_route_active (); + virtual void route_active_changed (); + + void disconnect_input (); + void disconnect_output (); + + void update_rec_display (); + void update_mute_display (); + void update_solo_display (); + virtual void map_frozen (); + + void reversibly_apply_route_boolean (string name, void (ARDOUR::Route::*func)(bool, void*), bool, void *); + void reversibly_apply_audio_track_boolean (string name, void (ARDOUR::AudioTrack::*func)(bool, void*), bool, void *); +}; + +#endif /* __ardour_route_ui__ */ diff --git a/gtk2_ardour/selectable.h b/gtk2_ardour/selectable.h new file mode 100644 index 0000000000..fdd6f7ff9f --- /dev/null +++ b/gtk2_ardour/selectable.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_selectable_h__ +#define __ardour_gtk_selectable_h__ + +class Selectable +{ + public: + Selectable() { + _selected = false; + } + + virtual ~Selectable() {} + + virtual void set_selected (bool) { + _selected = true; + } + + protected: + bool _selected; +}; + +#endif /* __ardour_gtk_selectable_h__ */ diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc new file mode 100644 index 0000000000..71b957d517 --- /dev/null +++ b/gtk2_ardour/selection.cc @@ -0,0 +1,573 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include + +#include "regionview.h" +#include "selection.h" +#include "selection_templates.h" +#include "time_axis_view.h" +#include "automation_time_axis.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace SigC; + +struct AudioRangeComparator { + bool operator()(AudioRange a, AudioRange b) { + return a.start < b.start; + } +}; + +Selection& +Selection::operator= (const Selection& other) +{ + if (&other != this) { + audio_regions = other.audio_regions; + tracks = other.tracks; + time = other.time; + lines = other.lines; + } + return *this; +} + +bool +operator== (const Selection& a, const Selection& b) +{ + return a.audio_regions == b.audio_regions && + a.tracks == b.tracks && + a.time.track == b.time.track && + a.time.group == b.time.group && + a.time == b.time && + a.lines == b.lines && + a.playlists == b.playlists && + a.redirects == b.redirects; +} + +void +Selection::clear () +{ + clear_tracks (); + clear_audio_regions (); + clear_points (); + clear_lines(); + clear_time (); + clear_playlists (); + clear_redirects (); +} + +void +Selection::dump_region_layers() +{ + cerr << "region selection layer dump" << endl; + for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) { + cerr << "layer: " << (int)(*i)->region.layer() << endl; + } +} + + +void +Selection::clear_redirects () +{ + if (!redirects.empty()) { + redirects.clear (); + RedirectsChanged (); + } +} + +void +Selection::clear_audio_regions () +{ + if (!audio_regions.empty()) { + audio_regions.clear_all (); + RegionsChanged(); + } +} + +void +Selection::clear_tracks () +{ + if (!tracks.empty()) { + tracks.clear (); + TracksChanged(); + } +} + +void +Selection::clear_time () +{ + time.track = 0; + time.group = 0; + time.clear(); + + TimeChanged (); +} + +void +Selection::clear_playlists () +{ + /* Selections own their playlists */ + + for (PlaylistSelection::iterator i = playlists.begin(); i != playlists.end(); ++i) { + (*i)->unref (); + } + + if (!playlists.empty()) { + playlists.clear (); + PlaylistsChanged(); + } +} + +void +Selection::clear_lines () +{ + if (!lines.empty()) { + lines.clear (); + LinesChanged(); + } +} + +void +Selection::add (Redirect* r) +{ + if (find (redirects.begin(), redirects.end(), r) == redirects.end()) { + redirects.push_back (r); + RedirectsChanged(); + } +} + +void +Selection::add (Playlist* pl) +{ + if (find (playlists.begin(), playlists.end(), pl) == playlists.end()) { + pl->ref (); + playlists.push_back(pl); + PlaylistsChanged (); + } +} + +void +Selection::add (const list& pllist) +{ + bool changed = false; + + for (list::const_iterator i = pllist.begin(); i != pllist.end(); ++i) { + if (find (playlists.begin(), playlists.end(), (*i)) == playlists.end()) { + (*i)->ref (); + playlists.push_back (*i); + changed = true; + } + } + + if (changed) { + PlaylistsChanged (); + } +} + +void +Selection::add (const list& track_list) +{ + bool changed = false; + + for (list::const_iterator i = track_list.begin(); i != track_list.end(); ++i) { + if (find (tracks.begin(), tracks.end(), (*i)) == tracks.end()) { + void (Selection::*pmf)(TimeAxisView*) = &Selection::remove; + (*i)->GoingAway.connect (bind (slot (*this, pmf), (*i))); + tracks.push_back (*i); + changed = true; + } + } + + if (changed) { + TracksChanged (); + } +} + +void +Selection::add (TimeAxisView* track) +{ + if (find (tracks.begin(), tracks.end(), track) == tracks.end()) { + void (Selection::*pmf)(TimeAxisView*) = &Selection::remove; + track->GoingAway.connect (bind (slot (*this, pmf), track)); + tracks.push_back (track); + TracksChanged(); + } +} + +void +Selection::add (AudioRegionView* r) +{ + if (find (audio_regions.begin(), audio_regions.end(), r) == audio_regions.end()) { + audio_regions.add (r); + RegionsChanged (); + } +} + +void +Selection::add (vector& v) +{ + bool changed = false; + + for (vector::iterator i = v.begin(); i != v.end(); ++i) { + if (find (audio_regions.begin(), audio_regions.end(), (*i)) == audio_regions.end()) { + audio_regions.add ((*i)); + changed = true; + } + } + + if (changed) { + RegionsChanged (); + } +} + +long +Selection::add (jack_nframes_t start, jack_nframes_t end) +{ + AudioRangeComparator cmp; + + time.push_back (AudioRange (start, end, next_time_id++)); + time.consolidate (); + time.sort (cmp); + + TimeChanged (); + + return next_time_id - 1; +} + +void +Selection::replace (uint32_t sid, jack_nframes_t start, jack_nframes_t end) +{ + for (list::iterator i = time.begin(); i != time.end(); ++i) { + if ((*i).id == sid) { + time.erase (i); + time.push_back (AudioRange(start,end, sid)); + + /* don't consolidate here */ + + + AudioRangeComparator cmp; + time.sort (cmp); + + TimeChanged (); + break; + } + } +} + +void +Selection::add (AutomationList* ac) +{ + if (find (lines.begin(), lines.end(), ac) == lines.end()) { + lines.push_back (ac); + LinesChanged(); + } +} + +void +Selection::remove (Redirect* r) +{ + list::iterator i; + if ((i = find (redirects.begin(), redirects.end(), r)) != redirects.end()) { + redirects.erase (i); + RedirectsChanged (); + } +} + +void +Selection::remove (TimeAxisView* track) +{ + list::iterator i; + if ((i = find (tracks.begin(), tracks.end(), track)) != tracks.end()) { + tracks.erase (i); + TracksChanged(); + } +} + +void +Selection::remove (const list& track_list) +{ + bool changed = false; + + for (list::const_iterator i = track_list.begin(); i != track_list.end(); ++i) { + + list::iterator x; + + if ((x = find (tracks.begin(), tracks.end(), (*i))) != tracks.end()) { + tracks.erase (x); + changed = true; + } + } + + if (changed) { + TracksChanged(); + } +} + +void +Selection::remove (Playlist* track) +{ + list::iterator i; + if ((i = find (playlists.begin(), playlists.end(), track)) != playlists.end()) { + playlists.erase (i); + PlaylistsChanged(); + } +} + +void +Selection::remove (const list& pllist) +{ + bool changed = false; + + for (list::const_iterator i = pllist.begin(); i != pllist.end(); ++i) { + + list::iterator x; + + if ((x = find (playlists.begin(), playlists.end(), (*i))) != playlists.end()) { + playlists.erase (x); + changed = true; + } + } + + if (changed) { + PlaylistsChanged(); + } +} + +void +Selection::remove (AudioRegionView* r) +{ + audio_regions.remove (r); + RegionsChanged (); +} + + +void +Selection::remove (uint32_t selection_id) +{ + if (time.empty()) { + return; + } + + for (list::iterator i = time.begin(); i != time.end(); ++i) { + if ((*i).id == selection_id) { + time.erase (i); + + TimeChanged (); + break; + } + } +} + +void +Selection::remove (jack_nframes_t start, jack_nframes_t end) +{ +} + +void +Selection::remove (AutomationList *ac) +{ + list::iterator i; + if ((i = find (lines.begin(), lines.end(), ac)) != lines.end()) { + lines.erase (i); + LinesChanged(); + } +} + +void +Selection::set (Redirect *r) +{ + clear_redirects (); + add (r); +} + +void +Selection::set (TimeAxisView* track) +{ + clear_tracks (); + add (track); +} + +void +Selection::set (const list& track_list) +{ + clear_tracks (); + add (track_list); +} + +void +Selection::set (Playlist* playlist) +{ + clear_playlists (); + add (playlist); +} + +void +Selection::set (const list& pllist) +{ + clear_playlists (); + add (pllist); +} + +void +Selection::set (AudioRegionView* r) +{ + clear_audio_regions (); + add (r); +} + +void +Selection::set (vector& v) +{ + + clear_audio_regions (); + // make sure to deselect any automation selections + clear_points(); + add (v); +} + +long +Selection::set (TimeAxisView* track, jack_nframes_t start, jack_nframes_t end) +{ + if ((start == 0 && end == 0) || end < start) { + return 0; + } + + if (time.empty()) { + time.push_back (AudioRange (start, end, next_time_id++)); + } else { + /* reuse the first entry, and remove all the rest */ + + while (time.size() > 1) { + time.pop_front(); + } + time.front().start = start; + time.front().end = end; + } + + if (track) { + time.track = track; + time.group = track->edit_group(); + } else { + time.track = 0; + time.group = 0; + } + + time.consolidate (); + + TimeChanged (); + + return time.front().id; +} + +void +Selection::set (AutomationList *ac) +{ + lines.clear(); + add (ac); +} + +bool +Selection::selected (TimeAxisView* tv) +{ + return find (tracks.begin(), tracks.end(), tv) != tracks.end(); +} + +bool +Selection::selected (AudioRegionView* arv) +{ + return find (audio_regions.begin(), audio_regions.end(), arv) != audio_regions.end(); +} + +bool +Selection::empty () +{ + return audio_regions.empty () && + tracks.empty () && + points.empty () && + playlists.empty () && + lines.empty () && + time.empty () && + playlists.empty () && + redirects.empty () + ; +} + +void +Selection::set (list& selectables) +{ + clear_audio_regions(); + clear_points (); + add (selectables); +} + +void +Selection::add (list& selectables) +{ + AudioRegionView* arv; + AutomationSelectable* as; + vector arvs; + vector autos; + + for (std::list::iterator i = selectables.begin(); i != selectables.end(); ++i) { + if ((arv = dynamic_cast (*i)) != 0) { + arvs.push_back (arv); + } else if ((as = dynamic_cast (*i)) != 0) { + autos.push_back (as); + } else { + fatal << _("programming error: ") + << X_("unknown selectable type passed to Selection::set()") + << endmsg; + /*NOTREACHED*/ + } + } + + if (!arvs.empty()) { + add (arvs); + } + + if (!autos.empty()) { + add (autos); + } +} + +void +Selection::clear_points () +{ + if (!points.empty()) { + points.clear (); + PointsChanged (); + } +} + +void +Selection::add (vector& autos) +{ + for (vector::iterator i = autos.begin(); i != autos.end(); ++i) { + points.push_back (**i); + delete *i; + } + + PointsChanged (); +} diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h new file mode 100644 index 0000000000..30f6983efa --- /dev/null +++ b/gtk2_ardour/selection.h @@ -0,0 +1,134 @@ +/* + Copyright (C) 2000-2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_selection_h__ +#define __ardour_gtk_selection_h__ + +#include + +#include "time_selection.h" +#include "region_selection.h" +#include "track_selection.h" +#include "automation_selection.h" +#include "playlist_selection.h" +#include "redirect_selection.h" +#include "point_selection.h" + +class TimeAxisView; +class AudioRegionView; +class Selectable; + +class Selection : public SigC::Object +{ + public: + enum SelectionType { + Object = 0x1, + Range = 0x2 + }; + + TrackSelection tracks; + AudioRegionSelection audio_regions; + TimeSelection time; + AutomationSelection lines; + PlaylistSelection playlists; + RedirectSelection redirects; + PointSelection points; + + Selection() { + next_time_id = 0; + clear(); + } + + Selection& operator= (const Selection& other); + + SigC::Signal0 RegionsChanged; + SigC::Signal0 TracksChanged; + SigC::Signal0 TimeChanged; + SigC::Signal0 LinesChanged; + SigC::Signal0 PlaylistsChanged; + SigC::Signal0 RedirectsChanged; + SigC::Signal0 PointsChanged; + + void clear (); + bool empty(); + + void dump_region_layers(); + + bool selected (TimeAxisView*); + bool selected (AudioRegionView*); + + void set (list&); + void add (list&); + + void set (TimeAxisView*); + void set (const list&); + void set (AudioRegionView*); + void set (std::vector&); + long set (TimeAxisView*, jack_nframes_t, jack_nframes_t); + void set (ARDOUR::AutomationList*); + void set (ARDOUR::Playlist*); + void set (const list&); + void set (ARDOUR::Redirect*); + void set (AutomationSelectable*); + + void add (TimeAxisView*); + void add (const list&); + void add (AudioRegionView*); + void add (std::vector&); + long add (jack_nframes_t, jack_nframes_t); + void add (ARDOUR::AutomationList*); + void add (ARDOUR::Playlist*); + void add (const list&); + void add (ARDOUR::Redirect*); + + void remove (TimeAxisView*); + void remove (const list&); + void remove (AudioRegionView*); + void remove (uint32_t selection_id); + void remove (jack_nframes_t, jack_nframes_t); + void remove (ARDOUR::AutomationList*); + void remove (ARDOUR::Playlist*); + void remove (const list&); + void remove (ARDOUR::Redirect*); + + void replace (uint32_t time_index, jack_nframes_t start, jack_nframes_t end); + + void clear_audio_regions(); + void clear_tracks (); + void clear_time(); + void clear_lines (); + void clear_playlists (); + void clear_redirects (); + void clear_points (); + + void foreach_audio_region (void (ARDOUR::AudioRegion::*method)(void)); + void foreach_audio_region (void (ARDOUR::Region::*method)(void)); + template void foreach_audio_region (void (ARDOUR::AudioRegion::*method)(A), A arg); + template void foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg); + + private: + uint32_t next_time_id; + + void add (vector&); +}; + +bool operator==(const Selection& a, const Selection& b); + +#endif /* __ardour_gtk_selection_h__ */ diff --git a/gtk2_ardour/selection_templates.h b/gtk2_ardour/selection_templates.h new file mode 100644 index 0000000000..c2ca70b526 --- /dev/null +++ b/gtk2_ardour/selection_templates.h @@ -0,0 +1,80 @@ +/* + Copyright (C) 2000-2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_selection_templates_h__ +#define __ardour_gtk_selection_templates_h__ + +/* these inlines require knowledge of Region and Route classes, + and so they are in a separate header file from selection.h to + avoid multiplying dependencies. +*/ + +#include +#include + +#include "selection.h" + +inline void +Selection::foreach_audio_region (void (ARDOUR::AudioRegion::*method)(void)) { + for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) { + ((*i)->region.*(method))(); + } +} + +inline void +Selection::foreach_audio_region (void (ARDOUR::Region::*method)(void)) { + for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) { + ((*i)->region.*(method))(); + } +} + +template inline void +Selection::foreach_audio_region (void (ARDOUR::AudioRegion::*method)(A), A arg) { + for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) { + ((*i)->region.*(method))(arg); + } +} + +template inline void +Selection::foreach_audio_region (void (ARDOUR::Region::*method)(A), A arg) { + for (AudioRegionSelection::iterator i = audio_regions.begin(); i != audio_regions.end(); ++i) { + ((*i)->region.*(method))(arg); + } +} + +#if 0 + +template inline void +Selection::foreach_route (void (ARDOUR::Route::*method)(A), A arg) { + for (list::iterator i = routes.begin(); i != routes.end(); ++i) { + ((*i)->region.*(method))(arg); + } +} + +template inline void +Selection::foreach_route (void (ARDOUR::Route::*method)(A1,A2), A1 arg1, A2 arg2) { + for (list::iterator i = routes.begin(); i != routes.end(); ++i) { + ((*i)->region.*(method))(arg1, arg2); + } +} + +#endif + +#endif /* __ardour_gtk_selection_templates_h__ */ diff --git a/gtk2_ardour/send_ui.cc b/gtk2_ardour/send_ui.cc new file mode 100644 index 0000000000..25546fb92a --- /dev/null +++ b/gtk2_ardour/send_ui.cc @@ -0,0 +1,152 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include + +#include "utils.h" +#include "send_ui.h" +#include "io_selector.h" +#include "ardour_ui.h" +#include "gui_thread.h" + +using namespace ARDOUR; + +SendUI::SendUI (Send& s, Session& se) + : _send (s), + _session (se), + gpm (s, se), + panners (s, se) +{ + hbox.pack_start (gpm, true, true); + set_name ("SendUIFrame"); + + vbox.set_spacing (5); + vbox.set_border_width (5); + + vbox.pack_start (hbox, false, false, false); + vbox.pack_start (panners, false,false); + + io = new IOSelector (se, s, false); + + pack_start (vbox, false, false); + + pack_start (*io, true, true); + + show_all (); + + _send.set_metering (true); + + _send.output_changed.connect (slot (*this, &SendUI::ins_changed)); + _send.output_changed.connect (slot (*this, &SendUI::outs_changed)); + + panners.set_width (Wide); + panners.setup_pan (); + + gpm.setup_meters (); + gpm.set_fader_name ("SendUIFrame"); + + screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (slot (*this, &SendUI::update)); + fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (slot (*this, &SendUI::fast_update)); +} + +SendUI::~SendUI () +{ + _send.set_metering (false); + + /* XXX not clear that we need to do this */ + + screen_update_connection.disconnect(); + fast_screen_update_connection.disconnect(); +} + +void +SendUI::ins_changed (IOChange change, void* ignored) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &SendUI::ins_changed), change, ignored)); + if (change & ConfigurationChanged) { + panners.setup_pan (); + } +} + +void +SendUI::outs_changed (IOChange change, void* ignored) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &SendUI::outs_changed), change, ignored)); + if (change & ConfigurationChanged) { + panners.setup_pan (); + gpm.setup_meters (); + } +} + +void +SendUI::send_going_away (Redirect *ignored) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &SendUI::send_going_away), ignored)); + + delete this; +} + +void +SendUI::update () +{ + gpm.update_meters (); +} + +void +SendUI::fast_update () +{ + if (_session.meter_falloff() > 0.0f) { + gpm.update_meters_falloff (); + } +} + +SendUIWindow::SendUIWindow (Send& s, Session& ss) +{ + ui = new SendUI (s, ss); + + vpacker.set_border_width (5); + + hpacker.pack_start (*ui, true, true); + + vpacker.pack_start (hpacker); + + add (vpacker); + set_name ("SendUIWindow"); + + s.GoingAway.connect (slot (*this, &SendUIWindow::send_going_away)); + + delete_event.connect (bind (slot (just_hide_it), reinterpret_cast (this))); + +} + +SendUIWindow::~SendUIWindow () +{ + delete ui; +} + +void +SendUIWindow::send_going_away (Redirect *ignored) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &SendUIWindow::send_going_away), ignored)); + + delete this; +} + diff --git a/gtk2_ardour/send_ui.h b/gtk2_ardour/send_ui.h new file mode 100644 index 0000000000..744469b3c9 --- /dev/null +++ b/gtk2_ardour/send_ui.h @@ -0,0 +1,79 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_send_ui_h__ +#define __ardour_gtk_send_ui_h__ + +#include "gain_meter.h" +#include "panner_ui.h" + +namespace ARDOUR { + class Send; + class Session; + class Redirect; +} + +class IOSelector; + +class SendUI : public Gtk::HBox +{ + public: + SendUI (ARDOUR::Send&, ARDOUR::Session&); + ~SendUI(); + + void update (); + void fast_update (); + + IOSelector* io; + + private: + ARDOUR::Send& _send; + ARDOUR::Session& _session; + GainMeter gpm; + PannerUI panners; + Gtk::VBox vbox; + Gtk::VBox hbox; + + SigC::Connection screen_update_connection; + SigC::Connection fast_screen_update_connection; + + void send_going_away (ARDOUR::Redirect*); + void ins_changed (ARDOUR::IOChange, void*); + void outs_changed (ARDOUR::IOChange, void*); +}; + +class SendUIWindow : public Gtk::Window +{ + public: + SendUIWindow(ARDOUR::Send&, ARDOUR::Session&); + ~SendUIWindow(); + + SendUI* ui; + + private: + Gtk::VBox vpacker; + Gtk::HBox hpacker; + + void send_going_away (ARDOUR::Redirect*); +}; + +#endif /* __ardour_gtk_send_ui_h__ */ + + diff --git a/gtk2_ardour/splash.ppm b/gtk2_ardour/splash.ppm new file mode 100644 index 0000000000..850f4072f7 --- /dev/null +++ b/gtk2_ardour/splash.ppm @@ -0,0 +1,32 @@ +P6 +# CREATOR: The GIMP's PNM Filter Version 1.0 +321 216 +255 +fffUUUffffffDDDDDDDDDUUUfffUUUUUUUUUUUUUUUDDDUUU333DDDDDDUUUUUUDDDDDDDDD333333333DDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDfffUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUffffffUUUDDD333UUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUffffffUUUffffffDDDDDDDDDUUUfffUUUUUUUUUUUUUUUDDDUUU333DDDDDDUUUUUUDDDDDDDDD333333333DDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDfffUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUffffffUUUDDD333UUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUffffffUUUffffffDDDDDDDDDUUUfffUUUUUUUUUUUUUUUDDDUUU333DDDDDDUUUUUUDDDDDDDDD333333333DDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDwwwUUUUUUUUUUUUUUUUUUUUUDDD333UUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUwwwUUUUUUDDDDDDDDDfffUUUDDDDDDfffUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUUUUDDDwwwUUUUUUUUUUUUUUUUUUUUUDDD333UUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUwwwUUUUUUDDDDDDDDDfffUUUDDDDDDfffUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUUUUDDDwwwUUUUUUUUUUUUUUUUUUUUUDDD333UUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDfffUUUUUUUUUfffUUUfffUUUUUUUUUUUUDDDfffUUUUUU333DDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUfffUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUfffDDDUUUDDDUUUDDDfffUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUU333DDDUUUUUUUUUUUUUUUfffUUUfffUUUDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDUUU333UUUfffDDDfffDDDDDDUUUfffUUUfffDDDUUUDDDUUUUUUfffUUUUUUUUUfffUUUfffUUUUUUUUUUUUDDDfffUUUUUU333DDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUfffUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUfffDDDUUUDDDUUUDDDfffUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUU333DDDUUUUUUUUUUUUUUUfffUUUfffUUUDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDUUU333UUUfffDDDfffDDDDDDUUUfffUUUfffDDDUUUDDDUUUUUUfffUUUUUUUUUfffUUUfffUUUUUUUUUUUUDDDfffUUUUUU333DDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUfffUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUfffDDDUUUDDDUUUDDDfffUUUDDDDDDUUUfffUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUDDDDDDUUUffffffUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUDDDDDDDDDUUUDDDUUUDDD333DDDDDDDDDUUUUUUDDDDDDDDDUUU333DDD333UUU333UUUDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUU333UUUDDDDDD333DDDUUUDDDUUUDDDDDDUUUUUUUUUUUUfffUUUUUUDDD333DDDDDDUUUDDDUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUDDDDDDUUUffffffUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUDDDDDDDDDUUUDDDUUUDDD333DDDDDDDDDUUUUUUDDDDDDDDDUUU333DDD333UUU333UUUDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUU333UUUDDDDDD333DDDUUUDDDUUUDDDDDDUUUUUUUUUUUUfffUUUUUUDDD333DDDDDDUUUDDDUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUDDDDDDUUUffffffUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUDDDDDDDDDUUUDDDfffUUUDDDUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUfffUUUUUUDDDDDDUUUUUUUUUfffDDDDDDDDDUUUfff333DDDUUUDDDDDDUUU333UUUDDDUUUUUUDDDUUUDDDDDDDDDDDDfffUUUUUUUUUUUUDDDfffUUU333DDDDDD333UUUDDDUUUDDDUUUDDDUUUDDDUUU333DDDDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDfff333DDDDDDDDDDDDDDDUUUUUUUUUfffUUUDDDUUUUUUDDDDDDDDDUUUDDDDDD333UUUUUUUUUUUUfffUUUUUUUUUfffffffffUUUDDDUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUfffUUUUUUDDDDDDUUUUUUUUUfffDDDDDDDDDUUUfff333DDDUUUDDDDDDUUU333UUUDDDUUUUUUDDDUUUDDDDDDDDDDDDfffUUUUUUUUUUUUDDDfffUUU333DDDDDD333UUUDDDUUUDDDUUUDDDUUUDDDUUU333DDDDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDfff333DDDDDDDDDDDDDDDUUUUUUUUUfffUUUDDDUUUUUUDDDDDDDDDUUUDDDDDD333UUUUUUUUUUUUfffUUUUUUUUUfffffffffUUUDDDUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUfffUUUUUUDDDDDDUUUUUUUUUfffDDDDDDDDDUUUfff333DDDUUUDDDDDDUUU333UUUDDDUUUUUUDDDUUUDDDDDDDDDDDDfffUUUUUUUUUUUUDDDfffUUU333UUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDUUU333UUUDDDDDD333DDDDDD333333UUUUUUDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUDDDfffDDDDDDUUUffffffUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUUUUfffUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDUUU333UUUDDDDDD333DDDDDD333333UUUUUUDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUDDDfffDDDDDDUUUffffffUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUUUUfffUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDD333UUUUUUUUUfffUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUfffUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDD333fffUUUfffUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDD333333UUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUfffDDDDDDUUUfffUUUUUUUUUDDDUUUDDDUUUUUUDDDUUUfffUUUUUUDDDUUUDDDfffUUUDDDUUUDDDUUUDDD333UUUUUUUUUfffUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUfffUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDD333fffUUUfffUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDD333333UUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUfffDDDDDDUUUfffUUUUUUUUUDDDUUUDDDUUUUUUDDDUUUfffUUUUUUDDDUUUDDDfffUUUDDDUUUDDDUUUDDD333UUUUUUUUUfffUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUfffUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDD333fffUUUfffUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDD333DDDDDDDDD333UUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDfffUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDD333DDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUDDDDDDDDDDDDUUU333DDD333fffDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDD333DDDDDDDDD333UUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDfffUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDD333DDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUDDDDDDDDDDDDUUU333DDD333fffDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDD333DDDDDDDDD333UUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDfffUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDDDD333UUUUUU333UUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUfffUUUUUUUUUUUU333DDDUUUUUUDDDUUUUUUUUUUUU333UUUDDDUUUUUUUUUUUUDDDUUUUUUffffffDDDfffDDDDDDUUUUUUDDDUUUfffDDDUUUDDDfffDDDUUUDDD333UUUDDD333DDDDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUU333333DDDDDDUUUDDDDDDUUUDDDUUUUUUfffDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUfffUUUDDDDDDDDDDDDDDDUUUDDDDDD333UUUUUU333UUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUfffUUUUUUUUUUUU333DDDUUUUUUDDDUUUUUUUUUUUU333UUUDDDUUUUUUUUUUUUDDDUUUUUUffffffDDDfffDDDDDDUUUUUUDDDUUUfffDDDUUUDDDfffDDDUUUDDD333UUUDDD333DDDDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUU333333DDDDDDUUUDDDDDDUUUDDDUUUUUUfffDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUfffUUUDDDDDDDDDDDDDDDUUUDDDDDD333UUUUUU333UUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUfffUUUUUUUUUUUU333DDDUUUUUUDDDUUUUUUUUUUUU333UUUDDDUUUUUUUUUUUUDDDUUUUUUffffffDDDfffDDDDDDUUUUUUDDDUUUfffDDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUU333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUfffUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUU333DDDDDDUUUDDDDDDfffDDDUUUfffUUUDDDDDDfffDDDUUUDDDUUU333UUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUfffUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUU333UUUUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUfffDDDUUUUUUUUUUUU333DDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUU333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUfffUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUU333DDDDDDUUUDDDDDDfffDDDUUUfffUUUDDDDDDfffDDDUUUDDDUUU333UUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUfffUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUU333UUUUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUfffDDDUUUUUUUUUUUU333DDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUU333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUfffUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUU333DDDDDDUUUDDDDDDfffDDDUUUfffUUUDDDDDDfffDDDUUUDDDUUU333UUUDDDDDDDDDUUUDDD333DDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUffffffDDDUUUUUUDDDUUUDDDUUU333333DDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUfffDDDUUUUUUDDDUUUUUU333DDDUUUUUUfffUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUU333DDDUUUDDD333DDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUffffffDDDUUUUUUDDDUUUDDDUUU333333DDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUfffDDDUUUUUUDDDUUUUUU333DDDUUUUUUfffUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUU333DDDUUUDDD333DDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUffffffDDDUUUUUUDDDUUUDDDUUU333333DDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDfffUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDD333DDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUDDDDDDDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDfffUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDD333DDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUDDDDDDDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDfffUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDD333DDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUDDDDDDDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDfffUUUfffDDDDDDDDDUUUUUUDDDUUUDDDUUUDDD333DDDDDDDDDDDDDDDUUUffffffUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDD333DDD333DDD333DDDUUUDDDDDDDDDUUUUUUDDDUUUUUUUUU333DDDDDDDDDfffDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDfffUUUDDDUUUUUUUUUUUUUUUUUUfffUUUDDDUUUDDDUUUDDD333UUUUUUUUUUUUUUUfffDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDfffUUUfffDDDDDDDDDUUUUUUDDDUUUDDDUUUDDD333DDDDDDDDDDDDDDDUUUffffffUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDD333DDD333DDD333DDDUUUDDDDDDDDDUUUUUUDDDUUUUUUUUU333DDDDDDDDDfffDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDfffUUUDDDUUUUUUUUUUUUUUUUUUfffUUUDDDUUUDDDUUUDDD333UUUUUUUUUUUUUUUfffDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDfffUUUfffDDDDDDDDDUUUUUUDDDUUUDDDUUUDDD333DDDDDDDDDDDDDDDUUUffffffUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDD333DDD333DDD333DDDUUUDDDDDDDDDUUUUUUDDDUUUUUUUUU333DDDDDDDDDfffDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUfffDDDUUUUUUUUUUUU333DDDUUUUUUDDDDDDDDDDDDDDD333333333DDDDDD333DDD333DDDDDDDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDD333DDDUUUUUUUUUDDDDDD333DDD333DDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUUUUffffffUUUUUUfffUUUUUUUUUUUUUUUfffUUUfffDDDDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUffffffUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUfffDDDUUUUUUUUUUUU333DDDUUUUUUDDDDDDDDDDDDDDD333333333DDDDDD333DDD333DDDDDDDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDD333DDDUUUUUUUUUDDDDDD333DDD333DDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUUUUffffffUUUUUUfffUUUUUUUUUUUUUUUfffUUUfffDDDDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUffffffUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUfffDDDUUUUUUUUUUUU333DDDUUUUUUDDDDDDDDDDDDDDD333333333DDDDDD333DDD333DDDDDDDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUfffDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDD333UUU333333"""DDD333UUUDDDDDDDDDDDD333DDD333UUUUUUUUUDDDUUUUUUUUUUUUUUU333UUU333333DDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDD333DDDUUUDDD333DDDDDD333DDDDDDDDDfffUUUUUUUUUUUUffffffUUUUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDUUUUUUUUU333DDDUUUDDDUUUDDDffffffUUUUUUUUUUUUfffDDDUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUfffDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDD333UUU333333"""DDD333UUUDDDDDDDDDDDD333DDD333UUUUUUUUUDDDUUUUUUUUUUUUUUU333UUU333333DDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDD333DDDUUUDDD333DDDDDD333DDDDDDDDDfffUUUUUUUUUUUUffffffUUUUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDUUUUUUUUU333DDDUUUDDDUUUDDDffffffUUUUUUUUUUUUfffDDDUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUfffDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDD333UUU333333"""DDD333UUUDDDDDDDDDDDD333DDD333UUUUUUUUUDDDUUUUUUUUUUUUUUU333UUU333333DDDUUUDDDDDDUUUUUUUUUDDDUUUDDDDDD333DDDUUU333UUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUU333DDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDD333UUUDDDDDDUUUfffDDDDDDUUU333DDDDDDDDDUUUDDDUUUUUU333DDDfffUUUfffUUUDDDUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDD333DDDUUU333UUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUU333DDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDD333UUUDDDDDDUUUfffDDDDDDUUU333DDDDDDDDDUUUDDDUUUUUU333DDDfffUUUfffUUUDDDUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDD333DDDUUU333UUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUU333DDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUUUU333UUUDDDDDD333DDDUUUUUUUUUfffDDDDDDUUUDDDfffUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDD333DDD333DDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUU333DDDUUUUUUfffUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDffffffUUUUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUfffUUUUUUDDDfffUUUUUUDDDUUUUUUDDDfffDDDUUUDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUUUU333UUUDDDDDD333DDDUUUUUUUUUfffDDDDDDUUUDDDfffUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDD333DDD333DDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUU333DDDUUUUUUfffUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDffffffUUUUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUfffUUUUUUDDDfffUUUUUUDDDUUUUUUDDDfffDDDUUUDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUUUU333UUUDDDDDD333DDDUUUUUUUUUfffDDDDDDUUUDDDfffUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDD333DDD333DDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDfffUUUDDDDDDUUUDDDUUUUUUfffUUUDDD333333DDDUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDfffUUUUUUDDDDDDDDDUUUUUU333333DDDDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDUUU333DDDDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUfffDDDUUUDDDUUUDDDDDDDDDUUUDDD333DDDDDDUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUfffUUUfffUUUDDDDDDfffUUUDDDDDDUUUDDDUUUUUUfffUUUDDD333333DDDUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDfffUUUUUUDDDDDDDDDUUUUUU333333DDDDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDUUU333DDDDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUfffDDDUUUDDDUUUDDDDDDDDDUUUDDD333DDDDDDUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUfffUUUfffUUUDDDDDDfffUUUDDDDDDUUUDDDUUUUUUfffUUUDDD333333DDDUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDfffUUUUUUDDDDDDDDDUUUUUU333333DDDDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUDDDUUUfffUUUUUUDDDDDDUUU333DDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUfffDDD333DDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUUUU333UUU333DDDDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUfffDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUfffDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUDDDDDDUUU333DDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUfffDDD333DDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUUUU333UUU333DDDDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUfffDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUfffDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUDDDDDDUUU333DDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUfffDDD333DDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDD333DDDDDD333DDD333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333333DDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUfffUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDfffUUUDDDUUUDDDDDDDDDDDDDDD333DDDDDDUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDD333DDDDDD333DDD333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333333DDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUfffUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDfffUUUDDDUUUDDDDDDDDDDDDDDD333DDDDDDUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDD333DDDDDD333DDD333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333333DDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUfffUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDD333DDDDDDDDDUUUDDDUUUUUUDDDDDD333UUUDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDfffUUUDDDDDDDDDDDDDDD333333DDDUUU333DDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUUUUffffffUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDDDD333DDDDDD333DDDDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffUUUUUU333UUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUU333333DDDDDDDDDUUUUUUUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUDDDUUUUUUDDDDDD333UUUDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDfffUUUDDDDDDDDDDDDDDD333333DDDUUU333DDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUUUUffffffUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDDDD333DDDDDD333DDDDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffUUUUUU333UUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUU333333DDDDDDDDDUUUUUUUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUDDDUUUUUUDDDDDD333UUUDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDfffUUUDDDDDDDDDDDDDDD333333DDDUUU333DDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUUUUffffffUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDD333DDDUUUDDDDDDDDDDDDDDD333DDD333DDDDDDUUUDDDfffDDDDDDDDDDDDDDDUUUDDD333DDDUUUDDDDDDDDD333333DDDUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDfffDDDUUUDDDDDDDDDDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUDDD333DDDDDDUUUUUUfffUUUUUUUUUfff333DDDUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDDDDDDDDDD333DDD333DDDDDDUUUDDDfffDDDDDDDDDDDDDDDpppDDD333DDDUUUDDDDDDDDD333333DDDUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDfffDDDUUUDDDDDDDDDDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUDDD333DDDDDDUUUUUUfffUUUUUUUUUfff333DDDUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDDDDDDDDDD333DDD333DDDDDDUUUDDDfffDDDDDDDDDDDDDDDUUUDDD333DDDUUUDDDDDDDDD333333DDDUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDD333333UUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUDDD333DDD333DDDDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDfffUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDD333UUUUUUDDDDDDUUU333DDDDDDDDDDDD333DDDUUUDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDfffDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUfffUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUU333DDDDDDDDD333333UUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUVVVhhhjjjîîîDDDDDDUUUDDD333DDD333DDDDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDfffUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDD333UUUUUUDDDDDDUUU333DDDDDDDDDDDD333DDDUUUDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDfffDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUfffUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUU333DDDDDDDDD333333UUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUDDD333DDD333DDDDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDfffUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDDDD333333UUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDD333333DDDDDDDDDDDDDDDfffDDDUUUUUUDDD333DDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUU333DDDUUU333333DDDUUUDDDDDDDDDDDDUUUDDDDDDDDD333DDDDDD333UUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDDDD333333UUUiiiuuuqqqoooppp†††———»»»äääDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDD333333DDDDDDDDDDDDDDDfffDDDUUUUUUDDD333DDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUU333DDDUUU333333DDDUUUDDDDDDDDDDDDUUUDDDDDDDDD333DDDDDD333UUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDDDD333333UUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDD333333DDDDDDDDDDDDDDDfffDDDUUUUUUDDD333DDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDD333333DDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDD333UUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDD333333UUUUUUfffUUUDDD333DDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDfffDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDD333DDD333UUUUUU333DDDDDD333UUUUUUffffffDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDD333333DDDWWWrrršššsssWWW///444ŸŸŸ´´´´´´ßßß¿¿¿UUUUUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDD333333UUUUUUfffUUUDDD333DDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDfffDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDD333DDD333UUUUUU333DDDDDD333UUUUUUffffffDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDD333333DDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDD333UUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDD333333UUUUUUfffUUUDDD333DDDDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDUUUfffUUUUUUUUUUUUDDDDDDDDD333UUUUUUUUUDDD333DDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDUUUUUUDDDDDD333UUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUU333UUUDDDDDDUUUUUU333DDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333DDDDDDUUUDDDfffUUUfffDDDDDDUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDUUUfffUUUUUUUUUUUUmmm´´´´´´ðð𜜜UUUDDD333DDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDUUUUUUDDDDDD333UUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUU333UUUDDDDDDUUUUUU333DDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333DDDDDDUUUDDDfffUUUfffDDDDDDUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDUUUfffUUUUUUUUUUUUDDDDDDDDD333UUUUUUUUUDDD333DDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUfffUUUDDDDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUU333DDDDDDDDDDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDfffUUUUUUUUUDDD333DDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDD333UUUDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDD333DDD333DDDDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUfffUUUfffUUUDDDDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUUUUUUUDDD&&&===´´´´´´ööö‹‹‹DDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUU333DDDDDDDDDDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDfffUUUUUUUUUDDD333DDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDD333UUUDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDD333DDD333DDDDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUfffUUUfffUUUDDDDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUU333DDDDDDDDDDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDfffUUUUUUUUUDDD333UUUDDD333UUUDDDfffUUUDDDUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDD333DDDUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUfffUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUfffUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDD333UUUDDDfffUUUDDDUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDD333---$$$´´´´´´÷÷÷gggDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUfffUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUfffUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDD333UUUDDDfffUUUDDDUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDD333DDDUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDfffffffffDDDDDDUUUUUUDDD333DDDUUUDDDDDDfffUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUDDDUUUUUUDDD333UUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDfffUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUfff333UUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUDDD"""DDDDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDfffffffffDDDDDDUUUUUUDDD333DDD999888´´´¿¿¿öööDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUDDDUUUUUUDDD333UUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDfffUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUfff333UUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUDDD"""DDDDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDfffffffffDDDDDDUUUUUUDDD333DDDUUUDDDDDDfffUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUDDDUUUUUUDDD333UUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDfffUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDfffUUUUUUUUUDDDDDDUUUUUUDDDUUUfffUUUDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUDDD333333DDDUUUUUUDDDDDDDDD333DDDUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDfffUUUUUUUUUDDDDDDUUUUUUDDDUUUfffPPP´´´ÏÏÏÒÒÒDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUDDD333333DDDUUUUUUDDDDDDDDD333DDDUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDfffUUUUUUUUUDDDDDDUUUUUUDDDUUUfffUUUDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUDDD333333DDDUUUUUUDDDDDDDDD333DDDUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUUUUUUUUUU333DDDDDDUUUUUUUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDD333333UUUDDDUUUDDDDDD333333UUUUUUDDDfffUUUUUUUUUDDDDDDUUUDDDUUUDDDfffUUUfffUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDD333DDDDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDDDD333DDDUUU333DDDDDDUUUUUUUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUeee´´´æææ»»»DDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDD333333UUUDDDUUUDDDDDD333333UUUUUUDDDfffUUUUUUUUUDDDDDDUUUDDDUUUDDDfffUUUfffUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDD333DDDDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDDDD333DDDUUU333DDDDDDUUUUUUUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDD333333UUUDDDUUUDDDDDD333333UUUUUUDDDfffUUUUUUUUUDDDDDDUUUDDDUUUDDDfffUUUfffUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDD333DDD333333UUUDDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333UUU333UUUUUUDDDUUUDDDfffUUUUUUfffDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDfffUUUfffUUUUUUDDDfffDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDUUUUUUUUU333DDDDDD333DDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUzzz´´´ðð𜜜DDDUUUUUUUUUUUUUUUDDDDDDDDDDDD333DDD333333UUUDDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333UUU333UUUUUUDDDUUUDDDfffUUUUUUfffDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDfffUUUfffUUUUUUDDDfffDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDUUUUUUUUU333DDDDDD333DDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDD333DDD333333UUUDDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333UUU333UUUUUUDDDUUUDDDfffUUUUUUfffDDDUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDD333333DDDDDDUUUDDDDDDDDDDDD333333DDDDDDUUUDDDUUU333DDDDDDUUUDDDUUUDDDDDD333UUUffffffUUUUUUDDD333DDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUfffUUU333UUUDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUfffUUUUUUUUUUUUUUUDDDUUUUUUfffUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDD + + +•••´´´ööö‹‹‹UUUUUUUUUUUUDDDDDDDDDUUUDDD333333DDDDDDUUUDDDDDDDDDDDD333333DDDDDDUUUDDDUUU333DDDDDDUUUDDDUUUDDDDDD333UUUffffffUUUUUUDDD333DDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUfffUUU333UUUDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUfffUUUUUUUUUUUUUUUDDDUUUUUUfffUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDD333333DDDDDDUUUDDDDDDDDDDDD333333DDDDDDUUUDDDUUU333DDDDDDUUUDDDUUUDDDDDD333UUUffffffUUUUUUDDDDDDDDDUUUUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUU333333DDDUUUDDDDDDDDD333333DDD333DDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUUUU333UUUfffUUUUUUDDD333333DDD333UUUUUUDDDDDDDDDUUUfffUUUUUUDDDDDDDDDDDDUUUUUUDDDfffDDDDDDUUUUUUDDDDDDUUUDDDDDD333UUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDD333DDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUU333UUUUUUUUU333DDDUUUUUUUUUDDDDDDUUUUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUU­­­´´´÷÷÷gggDDDDDDUUUDDDDDDDDDUUU333333DDDUUUDDDDDDDDD333333DDD333DDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUUUU333UUUfffUUUUUUDDD333333DDD333UUUUUUDDDDDDDDDUUUfffUUUUUUDDDDDDDDDDDDUUUUUUDDDfffDDDDDDUUUUUUDDDDDDUUUDDDDDD333UUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDD333DDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUU333UUUUUUUUU333DDDUUUUUUUUUDDDDDDUUUUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUU333333DDDUUUDDDDDDDDD333333DDD333DDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUUUU333UUUfffUUUUUUDDD333333UUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDD333DDDDDDDDDDDDDDDDDDDDD333DDDDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUfffUUUUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUU333DDDUUUDDD333UUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDD333UUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUDDD´´´¿¿¿öööUUUDDDDDDDDDDDDDDDUUUDDD333DDDDDDDDDDDDDDDDDDDDD333DDDDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUfffUUUUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUU333DDDUUUDDD333UUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDD333UUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDD333DDDDDDDDDDDDDDDDDDDDD333DDDDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUfffUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUfffDDDUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDD333UUUDDD333UUUUUUDDDUUUDDDfffDDDfffUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDffffffDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD333UUUDDDUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDfffUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDD333DDDDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDD999´´´ÏÏÏÖÖÖDDDUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDD333UUUDDD333UUUUUUDDDUUUDDDfffDDDfffUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDffffffDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD333UUUDDDUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDfffUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDD333DDDDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUfffDDDUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDD333UUUDDD333UUUUUUDDDUUUDDDfffDDDfffUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDffffffDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUfffDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUfffDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDD333DDDDDDUUUUUUUUUUUUDDD333UUUUUUUUUDDDUUUUUUUUUfffDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDD333DDD333DDDUUUDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUUDDDUUU---'''´´´äää¼¼¼DDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUfffDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDD333DDDDDDUUUUUUUUUUUUDDD333UUUUUUUUUDDDUUUUUUUUUfffDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDD333DDD333DDDUUUDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUfffDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUfffDDDUUUDDDUUUDDDUUUDDDUUUfffDDDDDDfffUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333UUUUUUUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDfffUUUDDDUUUUUUUUUUUUfffDDDDDD333DDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUfffUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUfffDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDUUUfffDDDDDDfffUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333///???´´´îî¦DDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDfffUUUDDDUUUUUUUUUUUUfffDDDDDD333DDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUfffUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUfffDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDUUUfffDDDDDDfffUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333UUUUUUUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDfffUUUDDDUUUUUUUUUUUUfffDDDDDDDDDDDDDDDUUUDDDUUUDDDfffDDDDDDUUUDDDUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUUUUUUUUUU333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDD333UUUUUUUUUDDDDDDDDDDDDDDDDDDUUUfffUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUfffDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDfffDDDDDDUUUDDDUUUDDDDDDDDDDDD333DDDWWW´´´ôôôDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUUUUUUUUUU333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDD333UUUUUUUUUDDDDDDDDDDDDDDDDDDUUUfffUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUfffDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDfffDDDDDDUUUDDDUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUUUUUUUUUU333DDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUDDD333UUUDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDD333UUUUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUffffffDDDDDDUUUUUU333UUU333DDDUUUDDDUUUUUU333UUUDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDDDD333DDDDDDDDDDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUUUUfffUUUDDDDDDUUUfffUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUDDD333UUUDDDzzz´´´÷÷÷kkkDDDUUUDDDUUUDDD333UUUUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUffffffDDDDDDUUUUUU333UUU333DDDUUUDDDUUUUUU333UUUDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDDDD333DDDDDDDDDDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUUUUfffUUUDDDDDDUUUfffUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUDDD333UUUDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDD333UUUUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUffffffDDDDDDUUUUUU333UUUDDDUUUDDDfffDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDDDD333333DDDUUUUUUfff333DDDDDDUUUDDD333UUUfffDDD333UUUDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDUUUfffUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUfffUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDDDD333DDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDffffffUUUUUUDDDUUUDDDfffDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDDDD333333•••¹¹¹÷÷÷333DDDDDDUUUDDD333UUUfffDDD333UUUDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDUUUfffUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUfffUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDDDD333DDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDffffffUUUUUUDDDUUUDDDfffDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDDDD333333DDDUUUUUUfff333DDDDDDUUUDDD333UUUfffDDD333UUUDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDUUUfffUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUU333DDDDDDUUUDDDUUUDDDUUUUUU333333UUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUU333DDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUfffUUU333DDDDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUfffUUUUUUUUUfffUUUUUUDDDUUUDDDDDDDDD333UUUUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDfffDDDUUUUUUDDDDDDUUUfffUUUDDDDDDUUUfffDDDDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUU333DDDDDDUUUDDD­­­ÉÉÉäää333333UUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUU333DDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUfffUUU333DDDDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUfffUUUUUUUUUfffUUUUUUDDDUUUDDDDDDDDD333UUUUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDfffDDDUUUUUUDDDDDDUUUfffUUUDDDDDDUUUfffDDDDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUU333DDDDDDUUUDDDUUUDDDUUUUUU333333UUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUU333DDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUfffUUU333DDDDDDDDDUUUUUUUUUUUU333UUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDD333UUUUUUUUUDDD333DDDDDDDDDDDDUUUUUUDDD333UUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDD333UUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUfffUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUUUUfffDDDUUU```ttt~~~yyyuuupppDDD;;;TTT„„„···DDD333DDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDDDDDDDSSSUUUDDDUUUDDDUUUDDDUUUUUUYYYhhhˆˆˆsssDDDDDDUUUDDDUUUUUU333UUUUUUDDDUUUUUUDDDDDDUUUDDDDDDTTTeeesssvvv>>>===´´´ÜÜܼ¼¼333DDDDDDDDDDDDUUUUUUDDD333UUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDD333YYYVVVmmmsss|||vvv………ppp___UUUUUUfffUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUfffDDDUUUUUUffffffDDDDDDUUUDDD333DDD333DDDDDDWWWDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUWWW___yyy‰‰‰DDDUUUUUU333UUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDD333UUUUUUUUUDDD333DDDDDDDDDDDDUUUUUUDDD333UUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDD333UUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUfffUUUDDDUUUDDDUUUDDDDDDDDD333DDDDDDUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUDDD333DDDUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDD333UUUDDDDDDUUU333fffUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDGGGfff¥¥¥´´´’’’qqqlll¶¶¶¢¢¢‡‡‡„„„óóó€€€DDDDDDDDDfffUUUDDDDDDDDD333DDDDDDDDDDDDDDDKKK```ppp………íííUUUfffUUUUUUUUUDDDEEERRRmmm‘‘‘ÆÆÆõõõgggUUUUUUDDD333DDDDDDUUUDDDDDDDDDUUUUUUUUUMMMwww±±±¨¨¨‡‡‡tttkkk}}}sss………´´´ëëëÀÀÀDDD333DDDUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDD333UUUDDDDDD[[[~~~ººº­­­‡‡‡qqqnnnggg¦¦¦ÁÁÁ±±±ŸŸŸcccDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUU```iiirrr××׌ŒŒUUUDDDDDDDDD333DDDUUUDDDDDDDDDDDDDDDDDDCCCRRReee¨¨¨ºººDDDfffUUUDDDDDDDDD333DDDDDDDDDDDDDDDDDDUUUfffUUUTTTiiivvv××׌ŒŒUUUDDDDDDDDDUUUDDDCCCeee‡‡‡¶¶¶êêê”””333DDDDDDUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUDDD333DDDUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDD333UUUDDDDDDUUU333fffUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUU333UUUDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDDDD333UUUDDDDDDUUU333DDDDDDDDDDDDUUUUUUUUUfffUUUUUUUUUFFF\\\¬¬¬«««hhh^^^UUUDDDPPPbbb´´´´´´ÃÃÃñññDDDDDDDDDffffffUUUDDDDDDDDDUUU```nnnnnn\\\ooo‡‡‡„„„ÄÄÄ×××fffUUUUUUDDDDDDCCCLLLlll¦¦¦´´´´´´ýýýUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDTTTvvvÅÅÅŽŽŽaaaZZZUUUUUUUUU666***ŸŸŸ´´´ñññ‹‹‹333UUUDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDFFFkkk···¡¡¡eeeMMMUUUDDDDDD999$$$[[[½½½àààÚÚÚ„„„UUUDDDDDD333UUUDDDDDDUUU333FFFZZZcccgggxxx’’’–––úúúgggDDDDDDUUUUUUUUUUUUUUUDDD___ZZZiiilll}}}„„„ŽŽŽëë릦¦ffffffUUUDDDDDDDDDUUUDDDUUUDDDFFFoooooommmqqq{{{’’’–––úúúXXXDDDDDDDDDDDD444FFF[[[–––´´´´´´ñññ¿¿¿DDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUU333UUUDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDDDD333UUUDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUfffUUUDDDUUUUUUUUUUUUfffUUUfffUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUfffUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDD333UUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUU333UUUDDD;;;}}}ÃÃÃyyy\\\DDDfffDDDDDDDDD"""666´´´´´´ØØØ¾¾¾DDDUUUDDDfffDDDUUUUUUDDDUUUPPPœœœ~~~hhh<<<%%%‰‰‰´´´´´´æææ¿¿¿DDDDDDUUUUUU===MMMžžž«««‘‘‘’’’ªªª÷÷÷‹‹‹UUUDDD333DDDUUUDDDUUUDDDUUUUUU___¾¾¾oooUUUUUUUUUfffUUUfffUUUƒƒƒ´´´÷÷÷‹‹‹DDDDDDUUUDDDUUUDDDUUUfffUUUUUUDDDUUUUUUUUUUUUUUUDDDPPPcccÏÏÏNNNUUUUUUDDDDDDUUUDDD>>>vvv´´´ÝÝÝóóókkkDDDDDD333UUUDDDDDDDDDDDDFFFxxxGGG333xxx´´´´´´ÃÃÃõõõ333333333DDDUUUDDDfffDDDGGGttt€€€\\\444PPPªªª´´´´´´ôôôfffDDDUUUUUUDDDUUUUUUUUUUUUSSS‚‚‚eeeMMM'''ZZZ´´´´´´ÃÃÃõõõUUUDDDUUUUUUQQQ===………²²²–––ŸŸŸëëëµµµDDDUUUDDDUUUDDDUUUUUUfffUUUDDDUUUUUUUUUUUUfffUUUfffUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUfffUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDD333UUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDDDDfffUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUDDDfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDD333DDDDDDUUU333DDDDDDDDD333DDDDDDDDDDDDDDDDDD333DDD333333DDDUUUDDDUUUUUUDDDUUUUUU:::„„„ÑÑÑsssDDDUUUUUUUUUDDDDDDDDD---´´´´´´ïïï’’’DDDDDDUUUUUUfffDDDDDDDDDDDDUUUDDDDDDDDDUUU&&&RRR´´´´´´ðððDDDfffUUU>>>ttt›››rrr^^^KKKEEENNNËËËfffDDDDDDUUUUUUDDDDDDDDDUUUUUUKKKŸŸŸµµµmmmUUUUUUUUUUUUUUUUUUDDDUUU‹‹‹´´´÷÷÷UUUUUUDDDUUUDDDUUUDDDfffUUUUUUDDDUUUUUUUUUDDDDDDDDD999dddÎÎΛ››DDDUUUDDDUUUDDD333DDDDDDUUU(((´´´´´´éééÓÓÓDDDDDDDDDDDDDDD333DDD333333DDDUUUDDD111666´´´´´´ÔÔÔµµµDDDDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDD???ŒŒŒ´´´´´´÷÷÷xxxUUUfffDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDBBB´´´´´´ÖÖÖ¿¿¿DDDDDDDDDQQQUUUœœœ‡‡‡[[[TTTMMMBBB©©©………UUUDDDDDDDDDUUUUUUUUUDDDDDDfffUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUDDDfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDD333DDDDDDUUU333DDDDDDDDD333DDDDDDDDDDDDDDDDDD333DDD333DDDDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDUUU333DDDDDDUUUDDDDDDUUUUUUfffUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDUUUUUU333DDDUUUDDDDDDDDDDDDUUUUUUDDDfffUUUfffDDDUUUUUUUUUDDDUUU999………ÌÌÌyyyDDDUUUDDDUUUDDDDDDDDDUUU"""´´´´´´õõõkkkUUUDDDDDDfffUUUDDDUUUDDD333UUUUUUUUUDDDUUU---***´´´´´´÷÷÷xxxUUUDDDMMMƒƒƒ“““^^^DDDDDDUUUUUUCCC|||DDDDDDDDDDDD333DDDDDDUUUDDD555———ÅÅÅbbbDDDDDDUUUDDDUUUUUUDDDDDDUUUžžž¿¿¿øøøDDDDDDUUUDDDDDDUUUUUUfffUUUDDDDDDDDDDDDDDDUUUDDD222FFFÓÓÓµµµDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDD•••´´´ÅÅÅýýýmmmDDDDDDDDDUUUUUUDDDfffUUUfffDDDUUULLL´´´´´´ëëëµµµDDDUUUDDDUUUDDDUUUDDDDDDDDDUUU333DDDDDDttt´´´¿¿¿õõõDDDfffUUUDDDUUUDDD333UUUUUUUUUDDDUUUDDDDDDUUUDDD´´´´´´îîî®®®UUUDDDUUUXXX§§§jjjUUUDDDUUUDDDCCCmmmDDD333DDDDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDUUU333DDDDDDUUUDDDDDDUUUUUUfffUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDUUUUUU333DDDUUUDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUUUU333DDDDDDfff333DDDDDD333UUUUUUDDDUUUUUUUUUUUUfffUUUDDD333DDDDDD333DDDDDD333DDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDD555}}}ÏÏÏ{{{UUUUUUDDDUUUDDDDDD333DDDDDD---'''´´´ÃÃÃóóóDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDD---´´´¿¿¿õõõUUUUUURRRxxxœœœ333DDDDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUU555}}}ÙÙÙqqqDDDDDDUUUUUUUUU333DDDDDDfff333´´´ÏÏÏÒÒÒUUUDDDUUUUUUUUUUUUfffUUUDDD333DDDDDD333DDDDDD+++888­­­ÞÞÞdddUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUZZZ´´´´´´øøø²²²DDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUU´´´´´´ñññUUUUUUUUUDDDUUUDDDDDD333DDDDDDDDDDDDDDDeee´´´ÏÏÏÎÎÎUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUUUU´´´´´´óóó•••UUU333HHH´´´___UUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUUUU333DDDDDDfff333DDDDDD333UUUUUUDDDUUUUUUUUUUUUfffUUUDDD333DDDDDD333DDDDDD333DDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUDDD333UUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDfffDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUfffDDDDDD000dddØØØ………DDDUUUUUUDDDDDD333UUUDDDDDDDDD&&&???´´´ÖÖÖ¹¹¹DDDUUUUUUDDDUUUDDDUUUDDDUUUDDDUUUDDDUUUDDDUUU999'''´´´ÏÏÏÒÒÒUUUUUUbbb¢¢¢DDDUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDD)))dddØØØ‡‡‡333UUUUUUDDDUUUDDDDDDUUUDDDDDDDDD´´´äää¼¼¼DDDDDDDDDDDDDDDfffDDDDDDUUUDDDDDDUUUDDDDDD@@@}}}ÛÛÛŸŸŸDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDDDD999000´´´´´´ãããÅÅÅDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUfff---´´´´´´÷÷÷DDDUUUUUUDDDDDD333UUUDDDDDDDDDDDDUUUDDD"""eee´´´æææÀÀÀDDDUUUDDDUUUDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUU´´´´´´÷÷÷XXXDDDQQQ¹¹¹bbbUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUDDD333UUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDfffDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDDDD333UUU333DDDDDDUUUDDDUUUDDDDDDUUU333DDDDDD333DDDDDDDDDUUUUUUDDDUUUDDDUUUfffDDDUUUUUUUUUDDD333DDDDDDDDD333UUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUDDD)))TTTÓÓÓ¹¹¹UUUDDDUUUDDDDDDUUUDDDDDDDDD333DDD```´´´îîî®®®DDDUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUUUU///???´´´æææÃÃÃUUUGGG¿¿¿UUUDDDDDDDDDUUUUUU333DDDDDDDDDDDDDDDDDDUUUDDDDDD222???ÒÒÒ¿¿¿DDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUU---´´´îîî®®®333DDDDDDUUUDDDUUUDDDDDDUUU333DDDDDD333DDD"""SSSÃÃÃçççVVVUUUDDDUUUfffDDDUUUUUUUUUDDD333DDDDDD---´´´´´´ÌÌÌüüüDDDUUUDDDDDDUUUDDDDDDUUUUUUUUUUUU---´´´¹¹¹õõõUUUDDDUUUDDDDDDUUUDDDDDDDDD333DDDDDDDDDDDDzzz´´´ððð“““DDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDLLL´´´¿¿¿öööUUUAAA»»»UUUUUUUUU333DDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDDDD333UUU333DDDDDDUUUDDDUUUDDDDDDUUU333DDDDDD333DDDDDDDDDUUUUUUDDDUUUDDDUUUfffDDDUUUUUUUUUDDD333DDDDDDDDD333UUUUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDD333UUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDfffDDDDDDDDDUUU333DDD333UUUDDDUUUUUUDDDDDD333222???¹¹¹ÞÞÞUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDŒŒŒ´´´óóóUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDWWW´´´ððð–––RRRÄÄÄVVVUUUDDDUUUUUUUUUDDD333DDDDDDUUUUUUDDDDDDUUUUUU???%%%———ääävvvDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDD999'''´´´õõõ€€€UUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUEEE"""–––ÜÜÜ¡¡¡UUUUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDD===´´´´´´´´´úúúUUU333DDD333UUUDDDUUUUUUDDDDDD333---'''´´´ÉÉÉâââDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDD + + +•••´´´ööö‹‹‹UUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDD999´´´ÏÏÏÔÔÔUUUlll›››UUUUUUDDD333DDDDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDD333UUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDfffDDDDDDDDDUUU333DDD333UUUDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUfff333DDDUUUUUUUUUDDDUUUfffUUUUUUUUU333ffffffDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUDDDfff333DDDDDDUUUDDD333DDDDDDUUUDDDUUUDDDDDDUUUDDD333DDD333DDDDDDUUUDDDDDDDDD000%%%………ÚÚÚžžž333DDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDD¦¦¦´´´÷÷÷vvvDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDeee´´´÷÷÷†††   ¤¤¤UUUfffUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDDDD333UUUDDDcccÕÕÕÈÈÈUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUfff???´´´÷÷÷‹‹‹DDDUUUfffUUUUUUUUU333ffffffDDDDDDUUUUUUccc¹¹¹ïïïwwwDDDUUUUUUDDDfff333DDDDDDUUUDDD333DDDDDDUUU´´´´´´´´´úúúDDD333DDD333DDDDDDUUUDDDDDDDDD333&&&???´´´ÞÞÞµµµDDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDD­­­´´´÷÷÷XXXUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDD999´´´ããã¾¾¾–––ØØØUUUUUUUUUDDDDDDUUUDDDDDDDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUfff333DDDUUUUUUUUUDDDUUUfffUUUUUUUUU333ffffffDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUDDDfff333DDDDDDUUUDDD333DDDDDDUUUDDDUUUDDDDDDUUUDDD333DDD333DDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUDDD333UUUUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDfffDDDUUUDDDDDDDDDUUUUUUDDDUUU333DDDcccÆÆÆèèèDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUU===´´´ÃÃÃõõõDDDDDD333UUUUUUDDDUUUUUUDDDDDDDDDUUUfffDDDDDDUUUzzz´´´êêê³³³ÝÝÝDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDDDDUUU333DDDDDD...777­­­çççvvvUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUWWW´´´÷÷÷DDDUUUUUUUUUDDDUUUDDDUUUUUUDDD333UUUUUULLLžžžÉÉÉßßßDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUUUUUUUUUU´´´´´´´´´úúúUUUDDDDDDDDDUUUUUUDDDUUU333DDDUUUWWW´´´îî¦UUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUUUU´´´¿¿¿öööUUUUUUDDDUUUUUUDDDDDDDDDUUUfffDDDDDDUUUUUUDDDDDD999///´´´ÞÞÞ°°°èèèwwwDDDUUUUUUDDDDDDDDDDDDDDDUUU333DDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUDDD333UUUUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDfffDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDfffUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUBBB(((¦¦¦ÛÛÛ¡¡¡DDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDD---´´´ÔÔÔÀÀÀUUU333UUUDDDDDDUUUfffUUUDDDUUUfffUUUUUUDDDUUUUUU•••´´´ÌÌÌííí’’’UUUDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDD}}}ÌÌÌÝÝÝDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUU„„„¿¿¿øøøDDDDDDUUUDDDfffUUUUUUDDDUUUUUUUUUUUUUUU&&&KKK´´´àà๹¹DDDDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUU´´´´´´¹¹¹ùùùDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDzzz´´´ôôôUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDfffUUU´´´ÏÏÏÒÒÒDDDDDDUUUfffUUUDDDUUUfffUUUUUUDDDUUUUUUDDDDDDUUU&&&GGG´´´ÌÌÌÜÜÜÍÍÍDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDfffUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUfffDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUfffDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUU333DDDUUUDDDUUUUUUDDDUUUDDDkkk¿¿¿íííWWWDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDUUUDDD&&&???´´´ëëëÀÀÀUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDUUUUUU­­­´´´ÃÃÃîîîWWWUUUUUUfffUUUUUUUUUUUUDDD333UUUDDDUUUDDDfffDDD&&&555­­­ããã«««UUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUžžžÏÏÏÒÒÒDDDUUUDDDUUUDDDUUU333DDDDDDDDDUUUDDDDDD´´´ðððŠŠŠUUUUUUUUUfffDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDD´´´´´´ÉÉÉäää333DDDUUUDDDUUUUUUDDDUUUDDDDDDDDD•••´´´÷÷÷kkkUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDBBB ´´´æææÀÀÀUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUUUU^^^´´´´´´èè袢¢UUUUUUUUUUUUDDD333UUUDDDUUUDDDfffDDDDDDUUUfffDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUfffDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUU333DDDUUUDDDUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUU333DDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUfffDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDDUUUDDD333DDDUUUUUUUUUDDD333DDDDDDDDDDDDUUUUUUDDDDDD555(((¦¦¦ÓÓÓÊÊÊDDDDDDUUUUUUUUUUUUUUUDDDUUUDDD333DDDDDD```´´´ñññDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDD´´´´´´ÙÙÙ»»»ffffffUUUDDDUUUDDDfffDDDDDDDDDDDDDDDUUUUUUDDDDDD|||¹¹¹ïïïjjjUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUU333´´´ããã½½½DDDDDDDDDUUUDDDDDDDDDDDDUUUfffDDDDDD=== ­­­´´´÷÷÷xxxUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDDUUUDDD333DDD´´´´´´ÜÜܶ¶¶DDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDD­­­¹¹¹÷÷÷UUUUUUUUUUUUUUUDDDUUUDDD333DDDDDDDDDDDDDDD---´´´ðð𜜜DDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDD„„„´´´ÃÃÃîîîDDDUUUDDDfffDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUU333DDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUfffDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDDUUUDDD333DDDUUUUUUUUUDDD333DDDDDDDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDfffUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUfffDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDD333DDDUUUUUUDDDDDD333333DDDDDDDDDUUUUUUUUU333DDD333kkk´´´éé采‡DDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUŒŒŒ´´´÷÷÷‹‹‹UUUDDDUUU333DDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUU999´´´´´´îî‰ffffffDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDD333555¦¦¦ÉÉÉßßßDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDD555 ´´´ëëë»»»DDDUUUUUUUUUDDDDDDUUUUUUfffDDDDDDDDD&&&222´´´¿¿¿õõõUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDD333DDDUUUUUU´´´´´´ëëë¼¼¼DDDDDDUUUUUUUUU333DDD333DDDDDDDDD´´´ÉÉÉäääDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUU999888´´´÷÷÷‹‹‹333DDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUfffžžž´´´ÙÙÙ···DDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDD333DDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDfffUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUfffDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDD333DDDUUUUUUDDDDDD333333DDDDDDDDDUUUUUUUUU333DDDUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDD333DDDDDD333UUUDDDUUUUUUDDD333DDDDDDUUUDDD333UUUDDDDDD333DDD=== + + +¦¦¦¿¿¿ðððWWWUUUDDDfffDDDDDDUUUDDDDDDUUUDDDDDDUUUUUU¦¦¦´´´÷÷÷UUUUUUUUUUUUDDDDDDUUUUUUUUUffffffUUUDDDUUUUUUUUU---'''´´´ÃÃÃñññfffUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDDDDD333DDD&&&RRR´´´àà๹¹UUUfffDDDUUUUUUDDDUUUUUUUUUDDDUUUDDDDDD---!!!´´´ñññUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDjjj´´´ÏÏÏÎÎÎUUUDDDDDDDDDUUUDDDDDDDDD333DDDDDD333UUUDDDUUUUUU´´´´´´ðð𜜜DDD333UUUDDDDDD333DDDDDDDDDDDD---´´´ÞÞÞ»»»fffDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUDDDPPP´´´÷÷÷xxxDDDDDDUUUUUUUUUffffffUUUDDDUUUUUUUUUDDDUUUffffff´´´´´´îî‰UUUDDDUUUUUUDDDDDDDDDUUUDDDDDD333DDDUUUDDDDDDUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDD333DDDDDD333UUUDDDUUUUUUDDD333DDDDDDUUUDDD333UUUDDDDDD333DDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUU333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDfffDDDfffUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUU&&&:::´´´ÒÒÒÌÌÌUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUDDD===´´´ÃÃÃöööUUUDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDDUUU///???´´´ØØØ¸¸¸fffUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUU + + +´´´ïïŠUUUDDDDDDUUUDDDUUUDDDDDDDDDUUU333DDDDDD///???´´´ùùù€€€DDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDD•••´´´ãããÂÂÂUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDD555 ´´´´´´öööDDDUUUUUUDDDDDDUUUUUUDDDUUUUUU---///´´´îîî®®®DDDDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDDDD333UUU„„„´´´øøøDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDDUUUUUUfffUUULLL´´´¿¿¿óóóDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUU333DDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUU333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDfffDDDfffUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDD333DDDUUUUUUDDDDDDDDDUUUDDD333DDDDDDDDDUUUDDDUUU333333333DDDUUUfffUUUUUUUUUUUUDDDDDDDDD333333DDDDDD333DDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUfffDDD|||´´´éé饥¥DDDUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDD---´´´ÔÔÔ»»»UUUDDDUUUUUUUUU333DDDDDDUUUDDDDDDDDDUUUUUUUUUUUU```´´´ïïï›››fffDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUBBB­­­¹¹¹õõõWWWUUUUUUUUUUUUDDDDDDUUUDDDDDDDDD333DDDUUU```´´´÷÷÷xxxDDD333DDDDDDDDDUUUDDDUUU333333333DDD­­­´´´êêêÂÂÂUUUDDDDDDDDD333333DDDDDD333DDDUUUDDDUUUDDDDDD---´´´¹¹¹õõõgggDDDUUUUUUUUUUUUfffDDDDDDUUUUUU&&&GGG´´´õõõ‹‹‹DDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDD333333UUUžžž¿¿¿øøøUUUUUU333DDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUU---´´´ÒÒÒÍÍÍDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDD333DDDUUUUUUDDDDDDDDDUUUDDD333DDDDDDDDDUUUDDDUUU333333333DDDUUUfffUUUUUUUUUUUUDDDDDDDDD333333DDDDDD333DDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUU333UUU333DDDDDDDDDUUUUUUDDDDDDUUUUUUDDD333UUU333DDDDDDUUUDDDfffUUU333DDDDDDDDDUUUUUUUUUUUUDDDDDDUUU333DDDDDDDDDDDDDDDDDD333UUUfffUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDDDD===¦¦¦´´´ñññŠŠŠUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDD333&&&???´´´ëëë¼¼¼DDDDDDDDDDDDDDDUUUffffffUUUUUUDDDUUUfffUUUUUUDDDŒŒŒ´´´õõõ………fffDDDDDDUUUDDDUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDIII´´´ÉÉÉãããDDDUUUUUU333UUU333DDDDDDDDDUUUUUUDDDDDDUUUŒŒŒ´´´øøø333DDDDDDUUUDDDfffUUU333DDDDDDDDDUUU999´´´´´´îîî®®®333DDDDDDDDDDDDDDDDDD333UUUfffUUUUUUDDDUUUUUU999///´´´ÌÌÌáááUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDqqq´´´÷÷÷UUUDDDDDDUUUUUUUUUUUUDDDDDD333DDDDDDDDD[[[´´´ÏÏÏÎÎÎDDDDDDUUUffffffUUUUUUDDDUUUfffUUUUUUDDDDDDUUUUUU///???´´´éé饥¥UUUDDDUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUU333UUU333DDDDDDDDDUUUUUUDDDDDDUUUUUUDDD333UUU333DDDDDDUUUDDDfffUUU333DDDDDDDDDUUUUUUUUUUUUDDDDDDUUU333DDDDDDDDDDDDDDDDDD333UUUfffUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUU333DDDDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDDDDUUUDDD333UUUUUUUUUUUUDDDUUUDDDDDDDDD333DDD333DDDDDDDDDfffDDDUUUDDDUUUUUUfffUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUU999+++´´´´´´÷÷÷UUUUUUDDDDDDUUUUUUUUUDDDUUUDDDUUU333DDDDDDsss´´´ðð𜜜DDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDD¦¦¦¿¿¿õõõUUUfffUUUUUUDDDUUUDDDDDDDDDUUUUUUDDDUUU333DDDDDD„„„´´´ÞÞÞÀÀÀDDDDDDDDDDDDUUU333DDDDDDUUUUUUDDDDDDUUUUUU¦¦¦¹¹¹ùùùDDDDDD333DDDUUUDDDDDDDDDUUUDDD333UUU999´´´´´´õõõ€€€DDDDDD333DDD333DDDDDDDDDfffDDDUUUDDDUUUUUUfff&&&GGG´´´ããã«««DDDUUUDDDUUUUUUUUUUUUUUUUUUUUUDDD•••´´´÷÷÷DDDUUUUUUUUUDDDUUUDDDUUU333DDDDDDDDDDDDUUU---###´´´ããã½½½UUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUWWW´´´óóóŠŠŠDDDUUUDDDDDDDDDUUUUUUDDDUUU333DDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUU333DDDDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDDDDUUUDDD333UUUUUUUUUUUUDDDUUUDDDDDDDDD333DDD333DDDDDDDDDfffDDDUUUDDDUUUUUUfffUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUU333333333DDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDD333333DDDDDD333DDD333333DDDDDDDDDUUUDDDDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDDDD333DDD333DDDUUUDDDUUUDDDUUUDDDUUUUUUDDDDDD333DDDUUUUUUDDDDDD333UUUUUUUUUDDD333YYY´´´ÃÃÃöööUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUžžž´´´øøøŒŒŒDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDUUU´´´ÏÏÏÎÎÎDDDDDD333UUUDDDDDDDDDDDDUUU333DDDDDD333DDD333UUU¦¦¦´´´îîŸ333DDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDD333"""´´´ÉÉÉâââ333333DDDDDDDDDUUUDDDDDDDDD333DDDUUU999888´´´´´´úúúDDD333DDD333DDDUUUDDDUUUDDDUUUDDDUUUUUUDDDDDDqqq¹¹¹ïïïjjjDDD333UUUUUUUUUDDD333UUUUUUDDDDDD­­­¿¿¿øøøUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDYYY´´´ëëëÀÀÀUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUfff„„„´´´÷÷÷gggDDDDDDDDDDDDUUU333DDDDDD333DDD333UUUDDDDDDDDD333333333DDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDD333333DDDDDD333DDD333333DDDDDDDDDUUUDDDDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDDDD333DDD333DDDUUUDDDUUUDDDUUUDDDUUUUUUDDDDDD333DDDUUUUUUDDDDDD333UUUUUUUUUDDD333333DDDDDDUUUUUUUUUDDDDDDDDDDDD333UUUUUUDDDDDDDDDDDDDDDUUUDDD333UUUDDDDDDUUUUUUUUUDDD333DDDDDDDDDUUUDDDDDDDDDDDD333333DDD333333UUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDD333DDD333DDDUUUUUUDDDDDDDDDŒŒŒ´´´ÔÔÔ»»»UUUUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333555´´´´´´÷÷÷‹‹‹DDDDDDDDDfffDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUU999´´´æææ»»»UUUUUUUUUUUUDDDDDDUUUDDD333333DDD333333DDDUUU555 ´´´´´´õõõ€€€DDDUUUUUUUUUDDDDDDDDDDDD333UUUUUUDDDDDDYYY´´´ÜÜܼ¼¼333UUUDDDDDDUUUUUUUUUDDD333DDDDDDDDDPPP´´´´´´úúúuuu333DDD333333UUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDD•••ÌÌÌÛÛÛDDD333DDDUUUUUUDDDDDDDDDDDD333DDD===´´´ÏÏÏÒÒÒUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUU333333 + + +´´´ñññfffDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDžžž¿¿¿öööUUUDDDDDDUUUDDD333333DDD333333DDDUUUDDDDDDUUUDDD333DDDDDDUUUUUUUUUDDDDDDDDDDDD333UUUUUUDDDDDDDDDDDDDDDUUUDDD333UUUDDDDDDUUUUUUUUUDDD333DDDDDDDDDUUUDDDDDDDDDDDD333333DDD333333UUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDD333DDD333DDDUUUUUUDDDDDDDDD333UUUDDDUUUDDDDDDDDD333DDDDDDUUUDDDUUU333UUUUUUUUUUUUDDD333DDD333DDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDD333DDD333333DDDDDD333UUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUDDDUUUUUUDDDUUUUUUUUUfffDDDDDDUUUDDD¦¦¦´´´êêê···DDDUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUUUU///AAA´´´´´´÷÷÷UUUDDDDDDffffffDDDUUUUUUDDDUUUDDDUUUDDDUUUUUUDDD---888´´´ðð𜜜UUUUUUUUUDDDDDD333333DDD333333333333333333DDD"""111´´´´´´ùùùŒŒŒDDDUUUDDDDDDDDD333DDDDDDUUUDDDUUU333UUU + + +´´´èè踸¸DDD333DDDDDDUUUUUUUUUDDDDDDDDDUUUDDDeee´´´´´´úúúDDD333UUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDLLL­­­ââ⢢¢UUUUUUUUUfffDDDDDDUUUDDDDDDDDDDDD999###´´´ãããÂÂÂUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUDDD333555'''­­­´´´úúú———fffDDDUUUUUUDDDUUUDDDUUUDDDUUUUUUDDDDDDUUUfffUUU´´´ÏÏÏÒÒÒDDDDDD333333DDD333333333333333333DDD333DDDDDDDDD333UUUDDDUUUDDDDDDDDD333DDDDDDUUUDDDUUU333UUUUUUUUUUUUDDD333DDD333DDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDD333DDD333333DDDDDD333UUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUDDDUUUUUUDDDUUUUUUUUUfffDDDDDDUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDD333333UUUDDDUUUDDDUUUDDDDDDDDD333DDD333DDDUUU333DDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUU555 ´´´´´´îî¦UUUUUUUUUUUU333DDDUUUUUUUUUUUUDDDDDDUUU|||´´´´´´úúúDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUfffUUUYYY´´´øøøŒŒŒUUUUUUUUUDDDDDDDDD333DDDDDD333333DDDDDD333333PPP´´´´´´÷÷÷kkkUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUBBB­­­´´´ëëë»»»DDDDDDUUUUUUUUUDDD333333UUUDDDUUUDDDeee´´´´´´úúú333DDDUUU333DDDDDDUUUDDDUUUUUUDDDDDDDDDUUU999+++¿¿¿ííífffUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDGGG´´´êêêÂÂÂUUU333DDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDkkk´´´´´´øøø‹‹‹DDDDDDDDDUUUUUUUUUUUUUUUDDDUUUfffUUUUUUfffUUU999´´´ãããÂÂÂDDDDDDDDD333DDDDDD333333DDDDDD333333333DDDDDD333333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDD333333UUUDDDUUUDDDUUUDDDDDDDDD333DDD333DDDUUU333DDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDD333DDD333DDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDD333UUUDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333DDDDDD---´´´´´´õõõ‹‹‹UUUDDDUUU333DDDUUUUUUDDDDDD333UUUDDD555(((¦¦¦´´´ÃÃÃöööUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDŒŒŒ´´´÷÷÷‹‹‹UUUUUU333DDD333333UUUDDD333UUUDDDDDDDDDDDDDDDooo´´´´´´øøøUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDUUUDDD[[[´´´´´´ñññ333DDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDeee´´´´´´úúúŒŒŒDDD333UUUDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUkkkÕÕÕÆÆÆDDDDDDDDDDDDDDD333DDDDDDDDDUUUUUUDDDqqq´´´îîî®®®333DDDUUUUUUDDDDDD333UUUDDDDDDDDDDDD;;;777¦¦¦´´´´´´÷÷÷gggDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUUUU///???´´´ëëëµµµDDD333333UUUDDD333UUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDD333DDD333DDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDD333UUUDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDfffDDDUUUUUUUUUUUUUUU333DDDUUUDDDDDDDDDDDDDDDUUUDDDUUU333DDDDDDDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDfffUUUUUUUUUUUUDDD333DDDDDDDDDDDDUUUDDDUUUUUU999888´´´´´´úúúŒŒŒDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUkkk´´´´´´ÔÔÔÀÀÀfffUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUUUUDDD¦¦¦´´´÷÷÷UUUUUUDDDDDDUUU333DDDDDDUUUDDDDDD333DDDUUUUUUDDDŒŒŒ´´´´´´úúúUUUUUUDDDDDDDDDfffDDDUUUUUUUUUUUUUUU///–––´´´´´´úúúDDDUUUDDDUUU333DDDDDDDDD333DDDDDDDDDeee´´´´´´úúúDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDfffUUULLL¹¹¹ÝÝÝYYYDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDUUU + + +•••´´´õõõ€€€DDDDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDAAAAAA{{{•••´´´´´´ùùùUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUUUUDDDUUUUUUfff```´´´ñññUUU333DDDDDDUUUDDDDDD333DDDUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDfffDDDUUUUUUUUUUUUUUU333DDDUUUDDDDDDDDDDDDDDDUUUDDDUUU333DDDDDDDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDfffUUUUUUUUUUUUDDD333DDDDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDfffUUUUUUUUUDDDUUUUUUUUUDDD333DDDDDDUUUUUUDDD333DDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDD333fffUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUU333333DDDDDD333DDDDDDUUUDDDUUUUUUUUUUUUPPP´´´´´´úúúŒŒŒUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDD888<<<™™™ŸŸŸ´´´èèèÃÃÃUUUDDDUUUDDDDDDUUUDDDUUUUUUfffUUUDDDUUUUUUUUU===´´´´´´úúúDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUU¦¦¦´´´´´´úúúDDDDDDDDDfffUUUUUUUUUDDDUUUUUUUUUDDDZZZ•••´´´´´´úúúuuuDDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDeee´´´´´´öööªªª333fffUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUJJJ××לœœ333DDDDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUU­­­´´´úúúŒŒŒDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDRRR```   TTTZZZ´´´´´´úúúDDDDDDUUUDDDUUUUUUfffUUUDDDUUUUUUUUUDDDUUUUUUUUUŒŒŒ´´´úúúDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDfffUUUUUUUUUDDDUUUUUUUUUDDD333DDDDDDUUUUUUDDD333DDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDD333fffUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUU333333DDDDDD333DDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333DDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDD333DDDDDDDDD333DDDDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUUUUDDDDDDDDD333333DDDUUUDDDUUUUUUDDDDDDUUUeee´´´´´´úúúŒŒŒUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDBBBgggzzzMMMŽŽŽ´´´èèèÃÃÃDDDDDDDDDDDDUUUDDDUUUffffffDDDUUUUUUUUUDDDDDD999###´´´´´´úúúDDDDDDUUUDDD333DDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUU´´´´´´´´´úúúDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD000”””```FFF´´´´´´úúúUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDGGG´´´´´´ççç¿¿¿DDDUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUUUU¹¹¹ÏÏÏFFF333DDDUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDBBB ´´´´´´úúúUUUUUUDDDUUUDDDDDDDDDDDDDDDCCCooo³³³bbbBBB000´´´´´´úúúDDDUUUDDDUUUffffffDDDUUUUUUUUUDDDDDDUUUDDDUUUUUU¦¦¦´´´úúú333DDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333DDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDD333DDDDDDDDD333DDDDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUUUUDDDDDDDDD333333DDDUUUDDDUUUUUUDDDDDDUUUUUUDDDUUUUUUfffUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUU333DDDDDDUUUDDDUUUDDDDDDUUU333333DDD333DDDDDDDDDDDDDDDDDDUUU333DDDUUUDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUfffDDDUUUUUUDDDeee´´´´´´úúúDDDDDDDDDUUUUUUDDDUUUDDDDDDCCCqqq½½½VVV%%%”””´´´èèè½½½DDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDD&&&GGG´´´´´´úúúUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUU333DDDDDDDDDDDD´´´´´´´´´ûûûUUUUUUfffUUUUUUUUUUUUDDDDDDDDDNNNžžžRRR"""´´´´´´úúúUUUDDDDDDUUU333333DDD333DDDDDDDDDDDD---'''´´´´´´ÓÓÓêêêDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDD'''ccc×××kkkDDDUUUUUUUUUUUUfffDDDUUUUUUDDDUUUDDDUUU"""!!!´´´´´´úúúUUUUUUDDDUUUDDDDDDDDDUUUFFF€€€¬¬¬QQQUUU999888´´´´´´úúúDDDUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUBBB ´´´´´´úúúDDDUUUDDDDDDDDDUUUUUU333DDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUfffUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUU333DDDDDDUUUDDDUUUDDDDDDUUU333333DDD333DDDDDDDDDDDDDDDDDDUUU333DDDUUUDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUfffDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDD333333DDDDDD333DDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUDDD333DDDDDDUUUUUUDDDUUUUUUDDDDDDDDDDDDUUUeee´´´´´´ööö–––UUUDDDDDDUUUUUUDDDUUUDDDSSSqqq¿¿¿aaaDDD¦¦¦´´´âââÄÄÄUUUDDD333UUUfffDDDUUUDDDDDDDDD333UUUDDDDDDUUUqqq´´´¹¹¹ùùùUUUDDDDDDDDD333DDD333UUUUUUDDDUUUDDDUUU333DDDDDD´´´´´´´´´þþþgggUUUUUUDDDUUUUUUDDDDDDDDDGGGžžžžžžDDD000´´´´´´ööö–––DDDDDDDDD333333DDDDDD333DDDDDDDDDDDDBBBªªª´´´½½½üüümmmDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDNNN>>>ÑÑÑ“““DDDUUUUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDD&&&???´´´´´´ööö–––UUUUUUDDDUUUDDDUUUUUUfff¯¯¯„„„UUU333UUUPPP´´´´´´ûûûUUUfffDDDUUUDDDDDDDDD333UUUDDDDDDUUUUUUUUUUUU---)))´´´´´´ùùù€€€333DDD333UUUUUUDDDUUUDDDUUU333DDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDD333333DDDDDD333DDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUDDD333DDDDDDUUUUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDfffUUUUUUDDD333DDDDDDDDDUUUUUUDDD333UUUDDDDDDDDDUUUDDDDDDUUUUUUUUUDDDUUU333DDDUUUDDDDDDUUUffffffDDDUUUDDDDDD333UUUDDDUUUDDDUUUDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUDDD[[[´´´´´´âââÕÕÕUUU333DDDDDDDDDUUUDDDQQQŒŒŒªªªaaaDDDDDD´´´´´´ÓÓÓæææDDDDDDUUUfffUUUEEE333333DDDDDDDDDDDDDDDDDDDDD •••´´´ÉÉÉâââUUUUUUDDD333UUU333UUUDDDUUUUUUDDDUUUDDDDDDUUUUUUªªª´´´´´´óóóŸŸŸUUUUUUUUUUUUDDDUUUDDDooo«««”””DDD333---´´´´´´âââÓÓÓ333UUUDDDDDDDDDUUUSSSDDDUUUUUUUUUDDDUUUvvv´´´´´´ìììÄÄÄffffffDDDUUUDDDDDD333UUUDDDUUU222¼¼¼———333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDWWW´´´´´´âââÏÏÏDDDDDDUUUDDDDDD@@@†††µµµcccDDDDDDUUUDDD"""eee´´´´´´ýýývvvUUU333333BBBµµµWWWDDDDDDDDDDDDDDDfffDDDDDDGGG´´´´´´÷÷÷^^^UUU333UUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUDDDfffUUUUUUDDD333DDDDDDDDDUUUUUUDDD333UUUDDDDDDDDDUUUDDDDDDUUUUUUUUUDDDUUU333DDDUUUDDDDDDUUUffffffDDDUUUDDDDDD333UUUDDDUUUDDDUUUDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDD333DDDUUUUUUDDDUUUDDD333333DDD333333DDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUU333DDDDDDUUUUUUUUUUUUUUU333DDDDDDUUUDDDDDDDDDDDD333DDDDDDUUUUUUUUUfffUUUUUUDDDUUUUUUUUU???´´´´´´ÅÅÅîî¤333DDDUUUUUUMMM~~~¹¹¹UUUDDD333333´´´´´´½½½òòò”””DDDUUUfff¤¤¤ÌÌÌDDD333DDDDDDDDDDDDDDDffffff­­­´´´ÜÜÜÂÂÂUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDD333ŒŒŒ´´´´´´ØØØîîîrrrUUUDDDUUUDDDeeeššš¯¯¯cccDDD333DDD999´´´´´´ÅÅÅðððDDD333<<<```žžžñññDDDDDDUUUUUUDDDUUU&&&&&&ªªª´´´ÌÌÌðððˆˆˆUUUUUUUUU333DDDDDDUUUGGGTTT¤¤¤333DDDDDDUUUUUUUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDeee´´´´´´ÅÅÅéé麺ºooo[[[VVV½½½ƒƒƒOOO333333DDDDDDUUUeee´´´´´´îîî´´´ccc___‰‰‰ÅÅÅ«««UUUDDDDDDDDDffffffDDD333DDD{{{´´´´´´øøøDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDD333DDDDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDD333DDDUUUUUUDDDUUUDDD333333DDD333333DDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUU333DDDDDDUUUUUUUUUUUUUUU333DDDDDDUUUDDDDDDDDDDDD333DDDDDDUUUUUUUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUfffUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUU---ªªª´´´´´´ÓÓÓááá´´´‚‚‚yyyššš¶¶¶•••HHHDDDUUUDDDDDDDDDŸŸŸ´´´´´´ØØØÛÛÛÉÉÉÎÎι¹¹|||CCCDDDUUUUUUUUUDDDUUUUUUUUUDDD´´´´´´èèèÃÃÃUUUUUUDDDDDDDDDDDDUUUUUUUUUDDDUUU333DDD333DDDDDDIII´´´´´´´´´áááÜÜܘ˜˜………€€€®®®²²²uuuOOO333DDDDDDUUU---´´´´´´´´´ØØØÛÛÛ»»»¿¿¿×××   ^^^DDDUUUUUUUUUDDDDDDDDDDDD + + +SSSªªª´´´ÝÝÝçç爈ˆUUUUUUUUUDDDUUU]]]˜˜˜dddUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDQQQ´´´´´´´´´ÅÅÅÚÚÚÓÓÓÍÍÍÉÉÉ”””TTTUUUDDDDDDDDDDDDDDDUUU[[[´´´´´´ÌÌÌßßßßßßÒÒÒ‘‘‘jjjUUUUUUDDDUUUUUUUUUfffUUUUUUUUUžžž´´´´´´úúúDDDDDDDDDUUUUUUUUUDDDUUU333DDD333DDDDDDUUUDDDUUUDDDDDDDDDUUUUUUfffUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUfffUUUfffUUUUUUDDDDDDDDD333UUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUfffUUU333 + + +NNN•••´´´¹¹¹ÉÉÉÓÓÓÃÃߟŸsss___DDDDDDDDDDDDDDDDDDUUUHHHŸŸŸÃÃþ¾¾›››ggg[[[DDDDDDDDDfffUUUDDDUUUUUUUUUfff///ZZZ±±±£££fffDDDDDDDDDUUUDDDfffDDDUUUDDDUUUDDDDDD333UUUDDDBBBnnnŸŸŸ´´´¿¿¿ÏÏÏÐÐп¿¿ŒŒŒpppTTTDDDDDD333UUUDDDDDD===qqqªªªÃÃþ¾¾›››‡‡‡sssXXXDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUMMM###DDD|||ªªªØØØÛÛÛ¹¹¹………€€€³³³¬¬¬mmmOOODDDUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUfffUUU333UUUfff///‰‰‰´´´¿¿¿¿¿¿¨¨¨“““sss___DDDDDDDDDDDDDDDUUUfffUUUUUU&&&+++ªªªÃÃÿ¿¿œœœ€€€```DDDfffUUUDDDUUUUUUUUUfffUUUUUUDDDLLL¿¿¿•••xxxÍÍÍDDDUUUDDDfffDDDUUUDDDUUUDDDDDD333UUUDDDUUUDDDDDDDDDDDDUUUfffUUUfffUUUUUUDDDDDDDDD333UUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUfffUUU333fffUUUUUUUUUDDDDDDDDDUUU333DDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDfffDDDDDDfffDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDUUUUUUUUU333DDDDDD???333HHHXXX]]]ccc^^^LLLPPPDDDUUUDDDDDDDDDUUUUUUUUUUUU]]]666NNNgggaaaWWWLLLUUUUUUUUUDDDUUUUUUUUUUUUUUUfffUUUfff***WWWdddQQQZZZUUUDDDUUU333DDDUUUfffUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUU666;;;NNNXXXbbbcccdddSSSJJJDDDUUU333DDDDDDDDDDDDDDDDDD333:::SSSgggaaaWWWYYYDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDfffDDD999@@@NNNcccvvv”””¥¥¥šššlll___LLLDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDUUUUUUUUU333DDDDDDDDDDDDDDD+++CCCXXXbbb^^^\\\QQQUUUDDDDDDDDDUUUUUUUUUUUUffffffUUU???%%%SSSgggjjjbbbUUUDDDUUUUUUUUUUUUUUUfffUUUfffUUUDDDUUU444666jjjQQQYYY333DDDUUUfffUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDfffUUUUUUUUUDDDDDDDDDUUU333DDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDfffDDDDDDfffDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDUUUUUUUUU333DDDDDDUUUfffDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUUUU333UUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffUUUUUUDDDDDDUUUfffDDDUUU333UUUDDD333UUU333UUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDfffUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUfffffffffDDDDDDUUUDDDfffDDDfffUUUUUUUUUUUUUUUUUUUUUDDDUUUfffUUUTTTUUUDDDUUUDDDUUUUUUDDDDDDDDDfffDDDDDDUUU333DDDDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUfffDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUUUU333UUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffUUUUUUDDDDDDSSSaaaKKK[[[333UUUDDD333UUU333UUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDfffUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUfffffffffDDDDDDUUUDDDfffDDDfffUUUUUUUUUUUUUUUUUUUUUDDDUUUfffUUUUUUUUUDDDTTTDDDUUUUUUDDDDDDDDDfffDDDDDDUUU333DDDDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUfffDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUUUU333UUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffUUUUUUDDDDDDUUUfffDDDUUU333UUUDDD333UUU333UUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUUUUUUUUUU333DDDDDDDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDD333fffDDDDDDDDDDDD333DDDUUUUUUUUUUUUUUUDDDDDD333UUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUUUUUUUDDDUUUffffff333UUUUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDDDDDDD333UUUUUUfffDDDUUUUUUDDDUUUUUUDDDUUUDDDfffUUUUUUUUU333DDDDDDDDDUUUUUUUUUDDDfffDDDUUUfffDDDUUUDDDDDDDDDUUUUUUUUUDDDDDD333DDDUUUUUUUUUDDDUUUUUUUUUUUU333DDDDDDDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDD333fffDDDDDDDDDDDD333DDDUUUUUUUUUUUUUUUDDDDDD333UUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUUUUUUUDDDUUUffffff333UUUUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDDDDDDD333UUUUUUfffDDDUUUUUUDDDUUUUUUDDDUUUDDDfffUUUUUUUUU333DDDDDDDDDUUUUUUUUUDDDfffDDDUUUfffDDDUUUDDDDDDDDDUUUUUUUUUDDDDDD333DDDUUUUUUUUUDDDUUUUUUUUUUUU333DDDDDDDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDD333fffDDDDDDDDDDDD333DDDUUUUUUUUUUUUUUUDDDDDD333UUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUfffDDDDDDUUUfffDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDDDD333DDDDDDUUU333DDDDDDDDDUUUUUUUUUDDDUUUDDD333DDDDDDDDDfffUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUfffDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDfffDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDDDD333DDDffffffDDDDDDUUUfffDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDDDD333DDDDDDUUU333DDDDDDDDDUUUUUUUUUDDDUUUDDD333DDDDDDDDDfffUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUfffDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDfffDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDDDD333DDDffffffDDDDDDUUUfffDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDDDD333DDDDDDUUU333DDDDDDDDDUUUUUUUUUDDDUUUDDD333DDDDDDDDDfffUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUU333DDDUUUDDDDDDUUUUUUfffDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDUUUfffDDDDDDDDDUUUDDDDDDDDDDDDfffUUU333DDDDDDDDDfffUUU333DDDUUUfffDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUfffUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUUUU333DDDUUUDDDDDDUUUUUUfffDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDUUUfffDDDDDDDDDUUUDDDDDDDDDDDDfffUUU333DDDDDDDDDfffUUU333DDDUUUfffDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUfffUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUUUU333DDDUUUDDDDDDUUUUUUfffDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDUUUfffDDDDDDDDDUUUDDDDDDDDDDDDfffUUU333DDDDDDDDDfffUUU333DDDUUUfffDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUUUUUUUUUU333DDDDDDUUUDDDUUUUUUfffUUUDDDUUUDDDUUUUUUDDDDDD333DDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDffffffDDDDDDUUUUUUDDDDDDDDDDDD333333333UUUDDD333DDDUUUDDDUUUUUUDDDUUUUUUUUUffffffUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUfffDDDUUUDDDDDDUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUUUUUUU333DDDDDDUUUDDDUUUUUUfffUUUDDDUUUDDDUUUUUUDDDDDD333DDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDffffffDDDDDDUUUUUUDDDDDDDDDDDD333333333UUUDDD333DDDUUUDDDUUUUUUDDDUUUUUUUUUffffffUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUfffDDDUUUDDDDDDUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUUUUUUU333DDDDDDUUUDDDUUUUUUfffUUUDDDUUUDDDUUUUUUDDDDDD333DDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDffffffDDDDDDDDDDDDDDD333DDDUUUDDDDDDUUU333DDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDfffUUUffffffUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUUUUfffUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDfffUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDDDD333UUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDUUU333DDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDfffUUUffffffUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUUUUfffUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDfffUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDDDD333UUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDUUU333DDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDfffUUUffffffUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUU333UUUDDD333DDDUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDffffffUUUUUUUUUUUUDDDDDDUUUfffUUUUUUUUUfffUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUDDDUUUDDDDDD333DDDUUUUUUUUUDDDUUUUUUUUUfffDDDUUUDDD333UUUUUUUUUfffUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDfffUUUUUU333UUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUU333UUUDDD333DDDUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDffffffUUUUUUUUUUUUDDDDDDUUUfffUUUUUUUUUfffUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUDDDUUUDDDDDD333DDDUUUUUUUUUDDDUUUUUUUUUfffDDDUUUDDD333UUUUUUUUUfffUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDfffUUUUUU333UUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUU333UUUDDD333DDDUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDffffffUUUUUUUUUUUUDDDDDDUUUfffUUUUUUUUUfffUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDD333DDDDDDUUUUUUDDDDDDUUUfffUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDffffffUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUfffUUUDDDUUUUUUUUUDDDUUUfffDDDUUUfffUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDUUU333333DDDDDDDDDDDDfffUUUUUUUUUUUUffffffDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDD333DDDDDDUUUUUUDDDDDDUUUfffUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDffffffUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUfffUUUDDDUUUUUUUUUDDDUUUfffDDDUUUfffUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDUUU333333DDDDDDDDDDDDfffUUUUUUUUUUUUffffffDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDD333DDDDDDUUUUUUDDDDDDUUUfffUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDffffffUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUfffUUUDDDUUUUUUUUUDDDUUUfffDDDUUUfffUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUffffffUUUUUUDDDUUUUUUUUUUUUfffUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDDDD333DDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUfffUUUfffffffffDDDUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDfffDDDUUUUUUDDDUUUUUUDDDUUUUUUDDDDDDDDDDDD333333UUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUffffffUUUUUUDDDUUUUUUUUUUUUfffUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDDDD333DDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUfffUUUfffffffffDDDUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDfffDDDUUUUUUDDDUUUUUUDDDUUUUUUDDDDDDDDDDDD333333UUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUffffffUUUUUUDDDUUUUUUUUUUUUfffUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUU333DDDfffUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUUUUDDDfffDDDUUUUUUUUUUUUUUUUUUfffDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDDDD333UUUUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUfffUUUfffDDDUUUDDDUUUUUUUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUU333DDDfffUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUUUUDDDfffDDDUUUUUUUUUUUUUUUUUUfffDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDDDD333UUUUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUfffUUUfffDDDUUUDDDUUUUUUUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUU333DDDfffUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUUUUDDDfffDDDUUUUUUUUUUUUUUUUUUfffDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUUUUfffDDDDDDDDDUUUUUUUUUfffUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUfffUUUUUUDDDDDDUUUfffDDDDDDfffUUUUUUDDDUUUUUUDDDDDDUUU333DDDDDDUUUUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUfffUUUfffUUUDDDUUUfffDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDD333333DDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUUUUfffDDDDDDDDDUUUUUUUUUfffUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUfffUUUUUUDDDDDDUUUfffDDDDDDfffUUUUUUDDDUUUUUUDDDDDDUUU333DDDDDDUUUUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUfffUUUfffUUUDDDUUUfffDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDD333333DDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUUUUfffDDDDDDDDDUUUUUUUUUfffUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUfffUUUUUUDDDDDDUUUfffDDDDDDfffUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDUUUfffUUUfffUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDfffUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUfffUUUUUUDDDUUUUUUfffUUUfffUUUUUUfffDDDUUUUUUUUUUUUUUUUUUfffUUUUUUUUUfffUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDUUUfffUUUfffUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDfffUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUfffUUUUUUDDDUUUUUUfffUUUfffUUUUUUfffDDDUUUUUUUUUUUUUUUUUUfffUUUUUUUUUfffUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDUUUfffUUUfffUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDfffUUUDDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDUUU333UUUUUUUUUUUUDDDUUUDDDUUUUUUfffUUUfffDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUfffUUUUUUDDDUUUfffUUUUUUUUUUUUffffffUUUUUUUUUUUUfffUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDD333DDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDUUU333UUUUUUUUUUUUDDDUUUDDDUUUUUUfffUUUfffDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUfffUUUUUUDDDUUUfffUUUUUUUUUUUUffffffUUUUUUUUUUUUfffUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDD333DDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDUUU333UUUUUUUUUUUUDDDUUUDDDUUUUUUfffUUUfffDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUU333UUUUUUDDDUUUDDDUUUUUUUUUDDDUUU333UUUDDDDDDUUUDDDDDDUUUUUUDDDUUUUUUUUU333DDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUfffUUUUUUDDDDDDDDDUUUUUUUUUfffUUUfffUUUUUUUUUUUUfffUUUUUUDDDUUUUUUUUUUUUUUUUUU333DDDDDDDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUfffUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUU333UUUUUUDDDUUUDDDUUUUUUUUUDDDUUU333UUUDDDDDDUUUDDDDDDUUUUUUDDDUUUUUUUUU333DDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUfffUUUUUUDDDDDDDDDUUUUUUUUUfffUUUfffUUUUUUUUUUUUfffUUUUUUDDDUUUUUUUUUUUUUUUUUU333DDDDDDDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUfffUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUU444VVVVVVEEEUUUDDDUUUUUUUUUDDDUUU333UUUDDDDDDUUUDDDDDDUUUUUUDDDUUUUUUUUU333DDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDD333DDDUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUfffDDDDDDDDDDDDDDDDDDUUUUUUDDDEEEVVVVVVEEEDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUfffDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUfffffffffDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUfffUUUDDDDDDUUUDDDUUUDDDDDDDDDfffUUUUUUUUUUUUUUUDDDDDDQQQQQQQQQ___DDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDD333DDDUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUfffDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUfffDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUfffffffffDDDUUUUUUUUUDDDDDDUUUEEEVVVVVVEEEVVVEEEEEEEEEVVVDDDDDDDDDDDDUUUUUUfffUUUDDDDDDUUUDDDUUUDDDDDDDDDfffUUUUUUUUUUUUUUUDDDDDD333333333DDDDDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUEEE444EEEVVVEEEEEEEEEWWWEEEEEEVVVEEEUUUfffDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUfffDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUDDD333DDDUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUVVVEEEVVVVVVVVVWWWVVVVVVEEEVVVUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUDDDUUUUUUUUUUUUfffUUUUUUDDDUUUDDDDDDDDDDDDUUUfffDDDUUUUUUUUUUUUDDDfffUUUDDDUUUUUUUUUfffDDDUUUUUUUUUUUUUUUDDDDDDUUUfffDDDDDDUUUDDDffffffDDDUUUDDDDDDDDDUUUDDD333DDDUUUfffUUUUUUUUU333DDDDDDQQQmmm______nnn___UUUUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUDDD333DDDUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUDDDUUUUUUUUUUUUfffUUUUUUDDDUUUDDDDDDDDDDDDUUUfffDDDUUUUUUUUUUUUDDDfffUUUDDDUUUUUUUUUfffEEEVVVVVVVVVWWWWWWFFFFFFWWWgggEEEEEEVVVDDDffffffDDDUUUDDDDDDDDDUUUDDD333DDDUUUfffUUUUUUUUU333DDDDDD333333DDDDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDEEEVVVVVVFFF555FFFXXXHHHHHHXXXXXXXXXHHHXXXWWWWWWVVVVVVEEEUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUDDDUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUUUU333DDDDDDUUUUUUDDDUUUUUUDDDUUU333UUUUUUUUUUUUUUUUUUUUUDDDUUUUUUVVVVVVWWWXXXXXXXXXYYYXXXXXXWWWWWWVVVVVVUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUffffffDDDUUUfffUUUVVVEEEVVVVVVgggVVVVVVVVVUUUUUUUUUUUUUUUDDDffffffUUUfffUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDD333333UUUUUUUUUUUUUUUUUUDDD333DDD†††______DDDUUUDDDDDDzzzUUUUUUUUUUUUUUUDDDDDDUUUEEEEEEEEEEEEVVVVVV444EEEEEEUUUUUUDDDUUUUUUDDDUUU333UUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUffffffDDDUUUfffUUUUUUDDDUUUUUUfffUUUUUUUUUUUUUUUUUUUUUUUUDDDffffffUUUgggVVVFFFXXXXXXXXXYYYHHHZZZHHHYYYHHHXXXFFFWWWVVVVVVUUUUUUDDDUUUDDDDDD333333UUUUUUUUUUUUUUUUUUDDD333DDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDVVVEEEEEEEEEFFFWWWXXX888IIIJJJ[[[\\\KKK\\\\\\KKK\\\:::ZZZZZZXXXXXXWWWWWWVVVDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUffffffDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDfffUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDVVVVVVXXXHHHZZZ\\\KKKLLL\\\ZZZZZZYYYXXXWWWgggVVVUUUDDDDDDUUUfffUUUUUUDDDUUUDDDfffUUUfffUUUVVVEEEVVVEEEFFFWWWEEEWWWFFFWWWhhhaaaoooaaannnVVVVVVDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDfffUUUUUUUUUfffUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUfffUUUDDDDDDDDDDDD†††UUUDDDUUUUUUDDDDDDDDDUUU†††UUUnnnUUUDDDEEEVVVEEEWWWWWWFFFhhhWWWFFFFFFEEEFFFVVVEEEEEEEEEDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUfffUUUUUUDDDDDDUUUfffUUUUUUDDDUUUDDDfffUUUfffUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDUUUfffDDDUUUDDDUUUUUUUUUDDDDDDDDDEEEVVVGGGHHHIIIZZZ\\\LLLmmm]]]]]]\\\mmm\\\[[[IIIXXXXXXWWWVVVUUUDDDDDDUUUUUUUUUUUUUUUUUUfffUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDEEEVVVFFFWWWXXXHHHjjjZZZKKKLLLMMMNNN___PPPPPPQQQQQQPPPPPP___^^^]]]\\\JJJIIIHHHFFFEEEEEEUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUfffUUUUUUDDDDDDUUUfffUUUUUUDDDUUUDDDfffUUUfffUUUUUUDDDUUUfffDDDUUUDDDDDDUUUDDDUUUUUUUUUDDD333333UUU333DDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUU333333333VVVWWWXXXZZZLLL^^^```aaa``````___NNNmmmZZZjjjXXXWWWEEEVVVDDDVVVEEEEEE___nnnnnnnnn}}}}}}ooopppppppppXXXHHHHHHZZZIIIZZZ888ŠŠŠŠŠŠqqqqqqcccppppppaaannn```EEEDDDUUUDDDDDDUUUUUUffffffDDDUUUUUUUUUfffUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUUUUfffUUUUUUUUUDDD333DDDzzzUUUfffUUUfffDDDDDDUUUUUUUUUUUU†††}}}```VVVFFFGGGXXXHHHYYYYYYZZZIII888888YYY888HHHGGGFFFFFFEEEVVVVVVVVVVVVVVVEEEVVVVVV444444444VVVVVVUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDfffUUUfffUUUUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUUUUffffffUUUUUUUUUUUUUUUDDDDDDUUUDDDUUU333ffffffUUUUUUDDDfffUUUUUUEEEVVVFFFHHHHHHZZZLLLMMM^^^```qqqqqqRRRbbbbbbaaappp___]]]\\\ZZZXXXWWWEEEEEEUUUUUUfffUUUUUUfffUUUUUUUUUDDD333DDDDDDUUUfffUUUfffDDDDDDUUUUUUUUUUUUUUUfffEEEWWWGGGHHHYYYIIIZZZ\\\]]]NNN???AAAbbbDDDTTTVVVVVVWWWWWWfffeeedddcccbbbPPP___]]];;;999777WWWVVVUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDfffUUUfffUUUUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUUUUffffffUUUUUUUUUUUUUUUDDDUUU333DDDUUUDDDDDDDDD333DDD333DDDDDD333UUUDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUEEEVVVXXXJJJ]]]PPPSSSVVVfffWWWfffdddSSS```^^^\\\KKKJJJHHHHHHHHHXXX~~~~~~}}}ppp~~~ppppppppppppcccrrrWWW;;;\\\\\\MMMfffttt€€€‚‚‚uuu]]]^^^tttttteeeddddddaaaaaaFFFVVVVVVVVVVVVUUUfffDDDUUUUUUUUUfffUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDUUUUUUfffDDDUUUDDDUUUUUUDDDDDDDDDnnnnnnUUUUUUDDD333DDDDDDVVVVVVVVVVVVpppaaappp777IIIZZZKKKLLLMMM===MMM===MMMMMM<<<\\\KKKZZZIIIIIIHHHHHHGGGGGGFFFWWWFFFFFFFFFWWWWWWFFFVVVVVVEEEVVVEEEEEEEEEUUUDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUfffUUUUUUUUUfffUUUUUUUUUUUUDDDUUU333333UUUUUUDDDDDDDDDUUUfffUUUUUUUUUUUUVVVEEEFFFFFFHHHIIIKKK\\\^^^```bbbdddtttWWWgggggggggvvvffffffdddbbbPPPMMM[[[HHHXXXEEEVVVUUUfffDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDD333DDDDDDUUUUUUUUUVVVVVVFFFXXX888III[[[LLLNNNOOO@@@RRRDDDUUUVVVIIIhhhYYYjjj[[[\\\[[[[[[[[[ZZZYYYgggVVVTTTRRR```^^^KKKYYYXXXEEEVVVDDDDDDDDDUUUDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUfffUUUUUUUUUfffUUUUUUUUUUUUDDDUUU333333fff333DDDDDDUUUUUUUUUDDDDDDDDD333DDD333UUUUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDVVVGGGZZZLLLQQQdddhhh[[[kkkkkk[[[iiihhhfffdddbbbPPPOOONNNVVV‚‚‚‹‹‹€€€dddjjjZZZ{{{kkkkkk\\\LLLMMMuuuiii``````kkk„„„kkkxxxzzzrrrcccccccccrrraaa```___MMM\\\[[[‰‰‰XXXGGGWWWFFFVVVVVVgggUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUU||||||UUUUUUUUUUUUDDDUUUDDDDDDzzzgggVVVVVVEEEEEEVVVVVVWWWWWWhhhiiiYYYjjj999MMM^^^``````RRRSSSSSSCCCSSSBBBaaa```OOO^^^NNNMMM\\\\\\KKKZZZJJJJJJIIIZZZIIIIIIIIIZZZHHHYYYHHHGGGXXXWWWFFFVVVVVVEEEVVVVVVVVVVVVUUUDDDDDDDDDDDDfffUUUfffUUUfffUUUwwwffffffUUUDDDDDDUUUDDDnnnnnn___DDDDDDUUUUUUfffUUUVVVVVVhhhXXXXXXYYYJJJ\\\]]]___aaaSSSeeeXXXhhhjjjzzzllllllkkkkkkkkkjjjhhhXXXUUURRR___\\\ZZZXXXWWWffffffUUUUUUUUUUUUDDDUUUDDDDDDDDD|||nnnUUUDDDDDDUUUUUUUUUVVVggghhhXXXjjj:::LLLNNN___aaabbbTTTVVVWWWdddrrrMMMkkklll^^^lll______nnnmmm^^^lll^^^\\\[[[hhhWWWUUURRR^^^KKKZZZGGGEEEVVVUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDfffUUUfffUUUfffUUUwwwffffffUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUfffDDDDDDVVVFFFYYYKKKOOOdddYYYlllnnn```nnnnnn}}}mmmttt€€€hhhWWW```ˆˆˆ‡‡‡yyybbbQQQ```NNN___>>>NNNOOO```PPPbbblll{{{VVV’’’|||pppXXXhhhYYYiiijjj[[[[[[jjjhhhffffffcccaaavvvggg\\\ZZZZZZjjjiiiXXXWWWWWWggggggggggggVVVEEEEEEEEEVVVEEEVVVVVVEEEzzz}}}nnnEEEVVVVVVEEEEEEEEEEEEooopppEEEFFFFFFXXXXXXhhhHHHjjjIIIZZZKKK\\\MMM___```cccVVVfffgggXXXXXXpppppp}}}|||oooeeeTTTcccRRR```PPP```___^^^^^^^^^nnnNNNNNN]]]MMM]]]LLLKKK[[[JJJZZZZZZHHHXXXXXXiiiWWWFFFWWWVVVEEEEEEVVVUUUUUUUUUDDDUUUDDDUUU333DDDDDDUUUDDDUUUlllzzz```nnnnnnEEE```VVVEEEVVVWWWGGGHHHZZZZZZ[[[]]]^^^```bbbTTTfffhhhjjjzzz{{{mmmnnnnnn||||||||||||nnn^^^[[[YYYfffSSS```]]]JJJHHHhhhVVVDDDUUUnnn____________nnn†††______DDDUUUUUUfffEEEgggFFFXXXIII[[[MMM^^^```bbbdddVVVhhhhhhsssssstttuuummmnnn```nnn```oooaaaooo```nnnnnnnnnnnnmmm{{{[[[YYYfffSSS___KKKHHHWWWEEEUUUUUUDDDUUUUUUfffUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDUUU333DDDDDDUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUfffUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDEEEXXXIIIMMMbbbgggkkknnnooopppppp{{{{{{zzz………aaawwwuuulllzzz[[[YYYgggVVVUUUTTTddddddFFFVVVXXXqqqrrrsssssskkk\\\]]]lll^^^nnnaaappp’’’………pppaaa]]]ZZZhhhUUUbbb‚‚‚ooonnnmmm[[[ZZZIIIYYYGGGXXXXXXFFFFFFFFFFFFWWWFFFFFFWWWWWWnnn{{{ppppppFFFWWWFFFFFFGGGXXXXXXqqqbbbHHHHHHjjjJJJZZZ[[[\\\MMM===^^^```QQQRRRTTT||||||wwwjjjjjjllllll‹‹‹tttttt€€€€€€sss[[[qqqhhhgggVVVVVVddddddTTTccccccbbbSSSSSSSSSbbbRRRQQQ```___^^^^^^]]]\\\\\\\\\[[[JJJIIIZZZHHHGGGWWWXXXWWWgggEEEEEEVVVEEEEEEEEEVVVVVV444EEE{{{aaaaaaHHHGGGXXX|||aaa~~~QQQpppIIIZZZlll]]]^^^PPPRRRSSSeeeWWWhhh[[[zzz||||||nnnnnnaaapppaaannnoooaaaaaa```^^^lll[[[XXXddd```NNN[[[YYYXXXEEE†††```______nnnnnn___nnnDDDooonnnDDDUUUVVVWWWGGG888[[[]]]OOORRRSSSfffgggxxxjjjllllll‚‚‚vvvwwwwwwnnn„„„aaaaaa```ooooooaaaaaaooopppaaannnnnnnnn___]]][[[fffSSSNNN[[[XXXVVVVVVUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUfffDDDDDDUUUDDDDDDDDDUUUUUU333DDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUUUUUUUfffDDDDDDVVVHHHJJJ^^^dddhhhllloooppprrrrrrqqq|||ggg|||¬¬¬~~~iiivvvuuufffssscccpppmmmjjj[[[[[[[[[jjj[[[\\\lll^^^µµµƒƒƒ______aaaaaapppdddfffvvv‹‹‹•••iii{{{………‚‚‚[[[YYYfff………SSSxxx```^^^nnn\\\lllkkkJJJZZZIIIIIIIIIIIIZZZZZZZZZ•••dddzzzrrrIII}}}rrrZZZIIIZZZJJJUUU€€€LLL\\\MMM]]]nnn^^^___```QQQbbbcccdddfffXXXhhhjjjŒŒŒfffmmmnnn```QQQnnn___```___mmm———‚‚‚]]]€€€jjjjjjjjjZZZhhhhhhhhhwwwYYYYYYgggXXXWWW||||||zzzcccbbbbbbbbb```PPP```NNNNNN]]]KKKKKKJJJZZZYYYHHHXXXHHHXXXXXXWWWFFFFFFGGGXXXcccdddZZZKKK[[[\\\KKKKKKKKKUUUffffffvvvwwwkkkllloooWWWhhhjjj[[[]]]mmm```aaaooooooooo}}}ppp}}}}}}aaapppaaaaaa``````mmmjjjhhhtttQQQNNN\\\dddyyypppWWWEEEVVVEEEEEEUUUDDDUUUNNN|||gggVVVWWWXXXIII\\\^^^aaadddWWWhhhjjjlll^^^mmmnnn```‰‰‰ooooooaaaŽŽŽwwwpppooonnn```nnnnnnnnnnnnaaaooooooooo~~~aaa___lll[[[VVVaaa\\\YYYWWWVVVUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDD333DDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUfffUUUUUUDDDEEEEEEHHH[[[pppeeejjjnnnqqqqqqeeeuuuvvvkkkyyy˜˜˜www¡¡¡|||pppoooooo{{{___vvvfffcccaaannnnnnOOO___nnnnnn˜˜˜aaaŽŽŽaaaRRRbbbcccrrrfffwwwzzzooošššqqq¢¢¢ŒŒŒ‰‰‰zzzaaa^^^[[[hhhžžž‰‰‰eeesssbbbaaa```nnn^^^^^^^^^^^^^^^NNNnnnNNNuuu}}}ggguuuuuuggg‰‰‰uuuNNNggguuuvvvžžž```PPPaaakkk†††zzzzzz{{{|||ooo}}}~~~rrr[[[\\\lllllluuunnnaaaŽŽŽSSSaaa```aaaaaaooo```nnnnnn˜˜˜ƒƒƒmmmvvv‚‚‚^^^lllzzzllllll]]]ttttttˆˆˆ“““’’’~~~hhhgggWWWffffffVVVdddbbbRRRPPP```vvvgggfffffftttWWWrrrJJJJJJJJJZZZ[[[;;;{{{zzz___```PPPPPPPPP@@@PPPOOOwwwyyyzzzooooooqqq€€€kkkvvv___```aaaooo}}}~~~ppp}}}oooooonnn|||nnnnnnoooooooooaaa}}}^^^kkkYYYVVVyyywwwfffœœœrrrIIIHHHpppWWWWWWVVVEEEVVVEEEggg‡‡‡XXXZZZ[[[gggwwwbbbVVVYYY[[[lllmmmnnnnnnnnnaaaiiiyyyaaaaaaaaawwwƒƒƒ```nnnmmmmmmllllll^^^nnn___nnnooopppaaaaaa___]]]hhhsss^^^ZZZXXXVVVVVVDDDUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDUUU333UUUDDDDDDDDDUUUUUU333DDDUUUUUUUUUDDDUUUUUUUUUUUUUUU333UUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUfffUUUUUUUUUDDD333EEEEEEHHH\\\pppVVV\\\aaadddtttvvv†††zzz‰‰‰………”””€€€ttt¨¨¨ˆˆˆ‚‚‚€€€€€€|||yyy‚‚‚dddppp~~~oooaaaooo˜˜˜aaaaaaiiipppqqqqqqrrrgggyyy}}}ŒŒŒŠŠŠ”””€€€oooxxxggg›››vvvmmmzzzjjj”””hhhXXXuuuVVVTTTSSSbbbSSSSSSSSSCCCSSSyyyŸŸŸlllyyyyyyŸŸŸŒŒŒyyy–––ŒŒŒ–––˜˜˜„„„¢¢¢………¤¤¤ššš›››‘‘‘’’’œœœ‰‰‰^^^ƒƒƒƒƒƒƒƒƒƒƒƒ„„„––––––‹‹‹xxxwww„„„„„„„„„„„„„„„ooopppoooaaa˜˜˜www„„„ƒƒƒnnnnnn___ƒƒƒwwwwww•••‰‰‰uuuttt]]]„„„‹‹‹yyy€€€ŒŒŒqqq~~~}}}‰‰‰………lll†††xxxxxxwwwvvvvvvuuuƒƒƒNNN^^^ooohhhzzzcccdddVVVVVVfffVVVeeeeee††††††oooggghhhyyy\\\lllmmmƒƒƒwwwaaa}}}oooppp~~~oooooonnn___^^^^^^^^^mmm___```aaaRRRaaannnmmmkkkZZZ’’’zzzxxxwwwŒŒŒsssttteeeJJJdddpppGGGXXXXXXccc€€€›››fffkkknnngggsss]]]mmmnnnoooooooooRRRooowwwwwwwwwƒƒƒƒƒƒƒƒƒ‚‚‚¦¦¦€€€€€€sssjjj[[[kkkŽŽŽŒŒŒƒƒƒnnnaaaRRRaaaaaa^^^iiisssOOOJJJGGGEEEVVVUUUfffUUUfffDDDUUUUUUfffDDDDDDfffUUUUUUUUUUUUUUUUUUfffDDDUUUfffUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUDDD333DDDDDDDDDUUUDDDUUUffffffUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDVVVEEEXXX[[[___VVVNNNppp‚‚‚iiixxx‰‰‰ppp———§§§––––––ŠŠŠ–––œœœ®®®––––––•••‰‰‰xxxfff€€€qqqaaapppxxxaaaoooiii„„„wwwppppppdddƒƒƒ‡‡‡~~~‚‚‚––––––‚‚‚~~~mmmwwwfff†††›››ooonnn|||ŽŽŽtttkkkyyyiiihhh~~~}}}ppppppcccccc¢¢¢›››°°°|||ˆˆˆ}}}pppppppppxxx………¾¾¾ššš¥¥¥‡‡‡œœœ–––———€€€ŒŒŒŒŒŒ‚‚‚www„„„wwwwwwwwwwww„„„ÀÀÀ‹‹‹kkkwwwwwwwwwƒƒƒwwwƒƒƒ}}}~~~ooooooaaa„„„„„„„„„„„„wwwwww˜˜˜aaaooowww„„„ooonnn```•••ŸŸŸ   ˆˆˆžžž¶¶¶}}}‚‚‚”””““““““’’’‡‡‡hhhhhhgggfffeee{{{ˆˆˆ‡‡‡yyylll‡‡‡dddooo|||hhhiii[[[kkk\\\\\\[[[”””sss˜˜˜lllmmmnnnnnnooooooaaappp}}}‘‘‘„„„ppp}}}nnn‚‚‚ŒŒŒŒŒŒ€€€€€€€€€uuuwwwjjjkkk„„„ƒƒƒ___€€€YYYŽŽŽ’’’lllwwwjjjOOOŒŒŒttt‚‚‚eee~~~rrrtttƒƒƒ‹‹‹€€€zzzWWWiii‹‹‹uuuwww„„„aaaaaaaaaaaaooonnnšššŽŽŽvvvuuuttt€€€sss~~~¬¬¬‰‰‰||||||VVV|||™™™ššš€€€\\\^^^nnn```oooaaammmhhhdddNNN999XXXgggEEEUUUfffDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUffffffUUUDDDfffUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDfffDDDDDDfffDDDDDDfffUUUDDDUUUffffffDDDEEEEEEGGGkkkNNNEEE[[[ppptttxxx{{{ppp   œœœ‹‹‹———–––——————®®®———–––”””ttt}}}€€€qqqooowww………ooonnn___nnnmmm”””ŸŸŸ~~~yyysssiiiooosssŠŠŠ–––‚‚‚~~~zzziiitttqqqbbb™™™ooonnniiinnnmmmuuu€€€ttt€€€ttthhhttt›››€€€“““{{{ttt€€€]]]]]]lllzzz–––ŒŒŒ“““ˆˆˆ{{{lllwwwƒƒƒƒƒƒ___}}}```nnn```aaaaaaooo}}}oooaaaaaa```ƒƒƒŠŠŠŠŠŠ___^^^llllllllllll^^^___¢¢¢aaaaaa}}}aaaxxx‘‘‘–––‹‹‹–––¯¯¯›››iiiwwwžžž‹‹‹wwwkkkwwwžžž´´´˜˜˜„„„¨¨¨‚‚‚••••••www‚‚‚‚‚‚lll]]]kkk[[[jjjiii~~~zzz………›››‘‘‘¤¤¤“““ttt‚‚‚ƒƒƒwwwƒƒƒƒƒƒ———mmm^^^^^^uuu„„„```aaaoooaaapppppppppaaappp˜˜˜www„„„ƒƒƒmmmttt€€€‰‰‰|||ooooooooo}}}rrrhhhvvvwww„„„xxxwww```———uuufffŒŒŒxxxhhhfff‘‘‘dddSSS†††xxxiiiiiiwww```RRR{{{}}}hhh[[[^^^ŠŠŠ•••   –––ŒŒŒwwwŒŒŒ–––ŠŠŠˆˆˆtttjjjiiihhhfffVVVTTTrrr„„„QQQppp‚‚‚•••———ŽŽŽVVVhhhyyyzzz^^^^^^^^^[[[vvvRRR===IIIXXXVVVVVVUUUDDDUUUDDDUUUUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUUUU333DDDfffUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDDDDfffUUUUUUUUUUUUUUUUUUfffUUUUUUfffUUUUUUDDDDDDEEEWWWYYYÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿWWWVVVDDDUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDUUUDDD333333DDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDDDD333333EEEEEEGGGZZZ___UUUjjjaaaggg†††nnn‰‰‰|||qqq~~~sssuuuvvvvvvƒƒƒwwwƒƒƒvvv¤¤¤ššš€€€|||ppp¢¢¢vvvˆˆˆ’’’sssssshhh~~~‡‡‡oooUUUUUUFFFgggššš“““¡¡¡hhh{{{–––„„„wwwŠŠŠ•••ƒƒƒwww‹‹‹–––wwwwwwaaa``````aaaxxxwwwƒƒƒ˜˜˜oooooonnnnnnoooiii„„„„„„nnnƒƒƒ„„„aaaoooooooooaaaooo```aaaaaaaaa```nnnnnn___^^^lll]]]\\\”””rrrqqqqqq|||oooaaa```mmm{{{|||}}}‘‘‘’’’ˆˆˆ‰‰‰”””‚‚‚‚‚‚‚‚‚‚‚‚ttt‹‹‹hhhhhh]]]^^^^^^lllmmm‚‚‚’’’„„„£££ƒƒƒ}}}oooaaaoooiii………………iii˜˜˜www„„„wwwƒƒƒnnnnnn___nnn|||```nnnaaaaaaaaappppppaaaaaaaaaaaaRRRoooxxx„„„ooopppaaaaaaaaaaaa```nnnmmmlll[[[jjjYYY’’’———‹‹‹OOOMMMLLLLLLMMMOOORRRVVVYYYjjjlllnnnnnnooooooooo˜˜˜ƒƒƒ```nnnnnnmmmllllll[[[jjjiiiiii[[[jjj\\\^^^vvvwww‚‚‚ŽŽŽoooaaaaaa„„„wwwvvvlllsssqqqooo{{{SSSAAA???NNN]]]\\\ZZZZZZrrrbbbbbbpppYYYZZZ[[[\\\^^^PPPSSSEEEEEETTTSSSPPP\\\ZZZGGGVVVEEEDDDfffDDDfffUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDD333DDDUUUUUUfffUUUUUUUUUUUUUUUUUUfffUUUUUUUUUUUUDDDDDD333UUUDDDEEEXXXZZZ\\\RRRXXX^^^rrrƒƒƒwwwxxxxxxyyymmm|||ooo~~~qqqrrrqqq}}}zzzqqqˆˆˆwww€€€~~~‡‡‡fffVVVdddyyyjjj```PPP@@@```aaassseeeppp```§§§–––www†††lllllllll^^^^^^———nnnwww```˜˜˜wwwwwwƒƒƒƒƒƒkkk¨¨¨§§§ƒƒƒ„„„ooo}}}nnnnnn”””aaaooo}}}vvvƒƒƒ„„„pppooonnn```nnn_________```QQQmmm{{{]]]\\\jjjiiihhh’’’fffUUUSSSSSSBBBPPP???OOO______pppbbbccc|||}}}~~~ŒŒŒ€€€€€€~~~qqqqqqIIIhhhYYYYYYiiijjjjjj\\\ttt‚‚‚ŽŽŽ¯¯¯•••ƒƒƒƒƒƒƒƒƒwwwƒƒƒwwwwww………iiixxx„„„„„„wwwxxxwwwnnnoooaaaoooaaapppppppppaaapppaaaRRRoooooo‘‘‘„„„oooooo```nnnnnn^^^^^^€€€€€€~~~|||ooo‚‚‚ŸŸŸvvvfffeeerrrbbbcccrrrsss===aaadddgggjjjlll|||nnnŽŽŽšššaaaooo}}}nnnnnnnnnnnnmmmmmmmmm^^^lll^^^___```aaakkk„„„aaa```nnnmmmllljjjhhhWWWUUURRR@@@NNN<<>>___OOONNN\\\ZZZXXXFFFEEEDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDfffUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDDDD333UUUDDDUUUUUUDDDfffUUUfffUUUUUUUUUUUUDDD333UUUUUUUUUUUUDDDfffUUUUUUDDDUUUDDDDDD444WWWXXXKKKOOOUUUxxx}}}ssstttƒƒƒfffggghhhvvviiixxxxxxxxxiiihhhfffrrrnnn€€€~~~|||zzzllljjjPPP@@@OOONNNMMMLLLKKK\\\ZZZ[[[\\\^^^OOOaaaddd˜˜˜ŽŽŽ………|||vvvfffgggXXXXXXYYYyyy[[[‹‹‹uuuŒŒŒ¯¯¯~~~ƒƒƒ‚‚‚vvv¦¦¦wwwwwwnnnnnnnnn___nnnnnnƒƒƒwwwnnn||||||vvvmmm„„„iiinnn^^^^^^lll]]]lllllllll\\\jjjiiiYYYXXXfffddd………RRRAAA```NNN^^^\\\KKKkkk[[[kkk[[[\\\]]]^^^PPPBBBcccddddddeeeUUUsssccccccSSSbbbSSSSSSEEEdddeeeWWWXXXYYYwwwŠŠŠ€€€tttuuu€€€–––wwwnnnnnnvvv„„„wwwwwwƒƒƒ„„„„„„„„„ƒƒƒnnnaaaaaaaaaRRRaaaaaaaaaaaaaaaooonnnnnnnnnnnn```———mmm^^^]]][[[€€€žžž||||||lllkkkiiiƒƒƒfffdddcccppp~~~```ooopppbbb€€€VVViiizzz|||~~~ŒŒŒƒƒƒƒƒƒ```nnn}}}}}}oooooopppaaa```nnn``````nnn```oooooopppaaaoooooo```___llljjjYYYWWWEEEbbbOOO]]]\\\IIIjjjXXXhhhWWWVVVVVVVVVEEE333UUUUUUUUUUUUEEEhhhXXXYYYIIIZZZKKKJJJ999YYYXXXFFFEEEEEEffffffUUUUUUfffDDDDDDDDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDDDDDDD333DDDDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUDDDDDDDDDDDD333DDDDDDVVVFFFYYYLLLbbbvvvlllooodddcccqqqcccpppaaapppbbbaaa``````lllkkkiiifffdddbbbPPPNNNNNNLLLKKKKKKKKKJJJHHHYYYXXXXXXXXXXXXHHHZZZZZZ\\\NNNOOOPPPxxx``````aaabbbbbbdddeeeWWW~~~qqq€€€†††ŒŒŒkkk\\\tttkkklll\\\kkkkkk\\\kkkkkklll‹‹‹‚‚‚zzzzzz\\\zzz‹‹‹sssŒŒŒ\\\[[[iiiYYYhhhYYYhhhgggWWWfffdddSSSqqqiiivvvNNNMMM\\\[[[ZZZIIIHHHXXXGGGHHHGGGGGGXXXIIIZZZKKKMMM^^^NNN___PPP___^^^NNNNNNNNNNNN===NNNNNN```PPPaaaRRRcccsssdddeee‡‡‡ppp~~~‰‰‰sssjjj\\\]]]]]]^^^mmmmmmnnnnnnnnnnnn^^^______```___````````````nnnnnnnnnllllll]]]lllllljjjŠŠŠqqqqqq’’’{{{yyybbb```^^^\\\[[[ZZZHHHXXXFFFVVVUUUUUUUUUDDDEEEQQQtttiiixxx{{{pppkkklll^^^|||}}}}}}```}}}aaaooooooaaaaaaoooaaaoooaaappppppaaaooonnn^^^zzziiiHHHTTTRRR___]]]\\\IIIHHHXXXFFFEEEEEEEEEUUUDDDUUUDDDDDDUUUDDDUUUDDDUUUVVVEEEFFFGGGGGG777GGGGGGWWWEEEVVVEEEUUUfffUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUfffDDDDDD333DDD333333DDDUUUEEEVVVHHHZZZ___dddhhhlll___nnn^^^lllMMMjjjZZZhhhWWWfffUUUdddcccbbb```^^^KKKJJJJJJYYYHHHXXXHHHGGGXXXWWWWWWEEEVVVVVV444EEEVVVFFFXXXHHHZZZrrrrrreeeKKK[[[KKKLLL^^^OOO```RRRbbbdddeeefffWWW‡‡‡{{{|||pppXXXXXXXXXvvvXXXgggggggggvvvvvvŠŠŠppp}}}||||||pppšššooouuuddddddSSSSSSSSSRRRaaa```___^^^‚‚‚tttKKKIIIIIIHHHGGGWWWFFFFFFEEEVVVVVVVVVVVVVVVWWWGGGHHHYYYZZZZZZ[[[[[[kkkKKKJJJ999JJJ999999JJJ[[[KKK\\\LLL]]]^^^^^^___wwwjjjxxxlllzzzEEEeeeVVVfffYYYhhhZZZjjjjjjjjjkkkkkk\\\\\\\\\lll]]]lll]]]]]]lllllllll\\\jjjiiiJJJYYYhhhXXX|||ooozzzyyyxxxPPPNNN]]]KKKJJJZZZHHHWWWFFFVVVVVVUUUUUUDDDDDDDDDEEEEEEGGGIIIKKKmmmPPPbbbeeegggwwwyyy[[[lll^^^mmm___``````nnnooo~~~ooooooaaaaaaaaaaaaooonnnmmmjjjhhhVVVSSSPPPNNNKKKIIIXXXGGGEEEEEEUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUfffDDDDDD444EEE555555EEEVVVEEEVVVDDDUUUUUUUUUUUUUUUDDDUUUDDDUUU333UUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUU333UUUUUUDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUfffUUU333DDDDDDDDD333UUUDDDUUUDDDVVVWWWYYY\\\```UUUhhhZZZjjjZZZXXXGGGTTTSSSQQQ```___^^^]]]\\\kkkZZZIIIHHH666VVVVVVWWWVVVEEEVVVVVVUUUDDDUUUDDDDDDUUUDDDUUUEEEVVVEEEFFFFFFWWWXXXGGGGGG777IIIIIIJJJKKK]]]NNN___pppqqqjjj]]]kkkkkkRRRSSSSSSSSSbbbSSSRRRrrrbbbbbbbbbbbbkkklllkkkxxxkkk„„„€€€‘‘‘``````OOONNNNNN]]]]]]\\\\\\[[[~~~cccHHH666WWWWWWFFFVVVEEEEEEDDDUUUDDDUUUDDDUUUUUUVVVEEEEEEVVVWWWFFFXXXhhhXXX666GGGFFFFFF555XXXGGGXXXHHHXXXYYYYYYZZZZZZKKK\\\LLL]]]NNNNNN???PPPPPPRRRbbbcccdddeeefffvvvfffXXXXXXIIIgggggghhhhhhYYYhhhhhhhhhXXXfffVVVUUUdddSSSbbbRRRaaaPPPNNNNNN\\\[[[JJJHHH777GGGFFFEEEEEEVVVDDDUUUffffffDDD333DDDDDDDDDEEEFFFHHHZZZKKKNNNpppbbbdddeeefffhhhZZZ[[[kkk]]]^^^mmm|||nnnnnn___```aaaooonnnnnnllljjjXXXdddQQQ===\\\ZZZHHHWWWEEEDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUfffUUU333DDDDDDDDD444VVVEEEVVVDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDDDD333DDDDDDDDDUUUUUUUUUUUUUUUfffUUUDDDDDD333UUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUfffDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUfffUUUffffffUUUDDD333DDDDDDUUUDDDDDDDDDUUUVVVVVVXXXZZZ]]]pppSSSdddEEEdddSSSAAANNNLLL\\\JJJZZZIIIXXXXXXWWWFFFVVVVVVVVVVVVVVVVVV333UUUDDDUUUUUUDDDUUUfffDDDUUUUUUUUUUUUDDDVVVEEEVVVVVVDDDVVVEEEVVVWWWFFFXXXXXXjjjkkkZZZKKK\\\LLLMMMLLLMMM]]]nnn^^^^^^^^^NNNnnn^^^^^^^^^^^^NNN^^^NNN^^^]]]MMMMMMmmm\\\KKKKKKJJJZZZYYYYYYXXXHHH”””XXXWWWFFFVVVVVVVVVUUUUUUDDDUUUfffDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUgggVVVggggggVVVEEE444EEEEEEVVVEEEEEEEEEVVVVVVVVVWWWWWWXXXhhhHHHXXX999ZZZJJJ999KKKKKK\\\MMM^^^OOO``````aaaRRRbbbbbbbbbbbbbbbbbbCCCbbbSSSbbbbbbRRRaaapppOOO^^^^^^^^^]]]LLL[[[JJJZZZYYYGGGWWWFFFVVVVVVDDDUUUUUUffffffUUUDDDUUUDDDDDDDDDDDDUUUfffVVVWWWXXXHHHkkk\\\]]]^^^```RRRcccUUUfffgggYYYZZZyyykkk]]]]]]]]]^^^lllllllllkkkZZZvvvccc```MMMZZZYYYXXXVVVVVVDDDUUUfffDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUfffUUUffffffUUUDDD333DDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUfffDDDUUU333UUUDDD333DDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUU333UUUDDDUUUUUUUUUDDDDDDDDDUUUDDDfffUUUDDDUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUfffUUUUUUDDD333DDDDDDDDD333DDDDDDUUUDDDDDDgggFFFHHHIII\\\^^^???___NNNNNNLLLJJJHHHXXXFFFEEEgggEEEVVVEEEVVVUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDfffUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUEEEgggVVVVVVWWWWWWGGGXXXHHH777HHHYYYZZZjjjZZZZZZZZZIIIZZZZZZZZZZZZIIIIIIZZZIIIIIIZZZZZZZZZjjjjjjXXXHHHˆˆˆaaaSSSpppppppppoooˆˆˆ{{{VVVVVVDDDUUUDDDDDDDDDUUUDDDfffUUUDDDUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUfffUUUUUUDDD333DDDDDDDDD333DDDDDDUUUDDDDDDgggEEEEEEEEEVVVVVV555WWWFFFFFFGGGHHHHHHYYYHHHJJJkkkKKK\\\LLL]]]]]]]]]]]]]]]]]]MMMMMMMMM]]]]]]MMMmmm\\\\\\[[[ZZZZZZYYYYYYHHHXXXGGGWWWEEEEEEVVVUUUUUUDDDfffUUUUUUUUUUUUDDDUUUDDD333DDDUUUUUUfffUUUUUUVVVEEEWWWXXXYYYZZZJJJKKK]]]NNNPPPaaabbbccctttuuufffXXXhhhYYYJJJhhhhhhhhhfffsssbbb^^^\\\IIIXXXFFFEEEDDDUUUDDDfffUUUDDDUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUfffUUUUUUDDD333DDDDDDDDD333DDDDDDUUUDDDDDDfffDDDDDDDDDUUUUUU333UUUDDDDDDDDDDDDDDDUUUDDDDDDfffDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUDDD333UUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDfffUUUDDDUUUEEEVVVWWWGGGYYYZZZZZZKKKZZZIIIHHHGGGWWWVVVVVVUUUfffUUUDDDUUUUUUUUUDDDUUUUUUDDDfffDDDUUUUUUUUUUUUffffffUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUfffUUUUUUUUUgggEEEEEEEEEVVVVVVFFFWWWFFFWWWWWWWWWWWWhhhWWWFFFWWWFFFhhhFFFWWWWWWWWWWWWWWWhhhWWWEEEVVVSSSaaa`````````nnnnnnnnn```nnnDDDDDDDDD333UUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDfffUUUDDDUUUDDDUUUUUUDDDUUUUUUUUUEEEVVVEEEEEEEEEVVVWWWWWWXXXhhhXXXHHHYYYYYYZZZHHHYYYYYYIIIjjjHHHYYYYYYYYYYYYiiiiiiXXXXXXWWWFFFEEEWWWWWWVVVVVVEEEUUUUUUUUUUUUUUUfffUUUUUUUUUfffDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUfffVVVEEEWWWFFFhhhHHHZZZZZZ[[[\\\]]]nnn```PPPaaaCCCSSSSSSSSSSSScccbbbaaaOOO]]]KKKHHHGGG555UUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDfffUUUDDDUUUDDDUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUUUUfffUUUDDDUUUUUUUUUDDDUUUUUUDDDfffDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUVVVVVVEEEWWWXXXGGGHHHGGGFFFWWWVVVEEEDDDUUUfffUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUUUUfffUUUUUUUUUUUUUUUUUUDDDDDDDDDfffUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDffffffDDDDDDUUUVVV444EEEEEEVVVggggggVVVVVVEEEEEEVVVVVVVVVVVVVVVVVVVVVgggVVVgggEEEEEEVVVEEEEEEDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUgggVVVEEEVVVWWWVVVVVVWWWFFFWWWFFFEEEWWWVVVgggVVVVVVVVVVVVVVVVVVEEEEEEEEEgggVVVUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDffffffDDDDDDUUUUUU333DDDDDDUUUffffffUUUUUUDDDDDDUUUVVVVVVVVVVVVWWWWWWhhhYYYjjjJJJKKK\\\LLLMMMNNNNNNNNN^^^^^^]]]KKK[[[IIIXXXFFFEEEUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUfffUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUUUUfffUUUUUUDDDDDDfffUUUDDDDDDDDDUUUUUUUUUUUUfffUUUDDDfffDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDD333EEEVVVVVV555EEEEEEVVVEEEDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDfffDDDUUUUUUDDDUUUUUUUUUffffffUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDfffUUUfffUUUUUUUUUUUUUUUUUUUUUfffUUUDDDfffUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUfffDDDUUUUUUDDDDDDUUUUUUDDDDDDfffUUUDDDDDDDDDUUUUUUUUUUUUfffUUUDDDfffDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDD333DDDUUUUUU333DDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUVVVVVVVVVEEEEEEEEEVVVEEEEEEUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDfffDDDUUUUUUDDDUUUUUUUUUffffffUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDfffUUUfffUUUUUUUUUUUUUUUUUUUUUfffUUUDDDgggVVVVVVWWWFFFGGGXXXHHHXXXHHHHHHIIIZZZZZZjjjIIIXXXXXXFFFEEEVVVUUUDDDDDDfffUUUDDDDDDDDDUUUUUUUUUUUUfffUUUDDDfffDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDD333DDDUUUUUU333DDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDUUU333DDDUUUDDDUUUDDDDDD333DDDDDDDDDDDDEEEEEEVVVEEEDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUfffUUUDDDUUUUUUUUUfffUUUUUUfffUUUUUUfffUUUUUUUUUUUUDDDDDDUUUDDDDDDfffUUUUUUUUUUUUDDDUUUDDDUUUfffUUUfffUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDUUU333DDDUUUDDDUUUDDDDDD333DDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUfffUUUDDDUUUUUUUUUfffUUUUUUfffUUUUUUfffUUUUUUUUUUUUDDDDDDUUUDDDDDDfffUUUUUUUUUUUUDDDUUUDDDUUUfffUUUfffUUUUUUUUUUUUDDDUUUEEEEEEEEEWWWEEEFFFWWWFFFWWWWWWFFFFFFVVVEEEEEEUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDUUU333DDDUUUDDDUUUDDDDDD333DDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUDDD333DDDUUUDDDDDDUUUUUUffffffUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDfffUUUDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUfffUUUDDDDDDffffffUUUUUUUUUUUUDDDDDDfffDDDDDDUUUUUUUUUUUU333DDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUffffffUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDfffUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUDDD333DDDUUUDDDDDDUUUUUUffffffUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDfffUUUDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUfffUUUDDDDDDffffffUUUUUUUUUUUUDDDDDDfffDDDDDDUUUUUUUUUUUU333DDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUffffffUUUUUUUUUUUUDDDUUUDDDUUUEEEEEEVVVVVVVVVEEEgggVVVVVVUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUDDD333DDDUUUDDDDDDUUUUUUffffffUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDfffUUUDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDfffDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDUUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDfffDDDDDDffffffUUUUUUDDDfffDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUfffUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDfffDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDUUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDfffDDDDDDffffffUUUUUUDDDfffDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUfffUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDfffDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDUUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUfffUUUDDDUUUfffUUUfffDDDDDDUUUDDDUUUUUUDDDDDDDDDDDDfffDDDDDDDDDDDDDDDDDDDDDDDDUUU333DDDUUUUUUDDDUUUDDDUUUUUUUUU333DDDDDD333DDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDfffUUUUUUUUUUUUDDDDDDUUUUUUfffDDDDDDUUUDDDDDDDDDDDD333UUUUUUDDDDDDUUUDDDDDDUUUUUUfffDDDDDDDDDDDDfffUUUDDDUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUfffUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUfffUUUDDDUUUfffUUUfffDDDDDDUUUDDDUUUUUUDDDDDDDDDDDDfffDDDDDDDDDDDDDDDDDDDDDDDDUUU333DDDUUUUUUDDDUUUDDDUUUUUUUUU333DDDDDD333DDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDfffUUUUUUUUUUUUDDDDDDUUUUUUfffDDDDDDUUUDDDDDDDDDDDD333UUUUUUDDDDDDUUUDDDDDDUUUUUUfffDDDDDDDDDDDDfffUUUDDDUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUfffUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUfffUUUDDDUUUfffUUUfffDDDDDDUUUDDDUUUUUUDDDDDDDDDDDDfffDDDDDDDDDDDDDDDDDDDDDDDDUUU333DDDUUUUUUDDDUUUDDDUUUUUUUUU333DDDDDD333DDDUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDfffUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDDDD333DDD333DDDDDDUUUDDDUUUUUUUUUDDDDDDUUUDDDfffUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDUUUUUU333DDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDDDD333DDDUUUUUUDDDDDDDDDUUUDDDUUUUUUfffDDDDDDUUUUUUfffUUUUUUfffDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUfffUUUUUUUUUUUUUUUfffUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDfffUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDDDD333DDD333DDDDDDUUUDDDUUUUUUUUUDDDDDDUUUDDDfffUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDUUUUUU333DDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDDDD333DDDUUUUUUDDDDDDDDDUUUDDDUUUUUUfffDDDDDDUUUUUUfffUUUUUUfffDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUfffUUUUUUUUUUUUUUUfffUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDfffUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDDDD333DDD333DDDDDDUUUDDDUUUUUUUUUDDDDDDUUUDDDfffUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUfffUUUfffDDDUUUUUUDDDUUUUUUUUUfffDDDUUUUUU333UUUfffUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUfffDDDfffUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDUUU333333DDDUUUDDDUUUDDDUUUDDDfffDDDDDDUUUfffDDDDDDUUUUUUDDDUUU333DDDUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUfffUUUfffDDDUUUUUUDDDUUUUUUUUUfffDDDUUUUUU333UUUfffUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUfffDDDfffUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDUUU333333DDDUUUDDDUUUDDDUUUDDDfffDDDDDDUUUfffDDDDDDUUUUUUDDDUUU333DDDUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUfffUUUfffDDDUUUUUUDDDUUUUUUUUUfffDDDUUUUUUDDDUUUfffUUUUUUUUUfffDDDUUUUUUDDDUUUfffDDDUUUDDDUUUUUUUUUDDDUUUfffUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDfffUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUffffffUUUDDDUUUUUUDDDUUUfffUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDUUUUUU333DDDUUUUUUUUUUUUDDDUUUfffUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUffffffUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUfffUUUUUUUUUfffDDDUUUUUUDDDUUUfffDDDUUUDDDUUUUUUUUUDDDUUUfffUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDfffUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUffffffUUUDDDUUUUUUDDDUUUfffUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDUUUUUU333DDDUUUUUUUUUUUUDDDUUUfffUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUffffffUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUfffUUUUUUUUUfffDDDUUUUUUDDDUUUfffDDDUUUDDDUUUUUUUUUDDDUUUfffUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDfffUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUffffffUUUDDDUUUUUUDDDfffUUUfffUUUDDDDDDDDDDDDDDDfffUUUUUUUUUfffUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDUUU333DDDDDDDDDDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUfffUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDUUUUUUfffDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUUUU333DDDUUUUUUUUUUUUDDDDDDUUUUUUfffUUUfffUUUUUUUUU333DDDUUUUUUDDDDDDfffDDDUUUDDDfffUUUfffUUUDDDDDDDDDDDDDDDfffUUUUUUUUUfffUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDUUU333DDDDDDDDDDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUfffUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDUUUUUUfffDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUUUU333DDDUUUUUUUUUUUUDDDDDDUUUUUUfffUUUfffUUUUUUUUU333DDDUUUUUUDDDDDDfffDDDUUUDDDfffUUUfffUUUDDDDDDDDDDDDDDDfffUUUUUUUUUfffUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDUUU333DDDDDDDDDDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUfffUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDffffffUUUUUUUUUfffUUUfffDDDDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUDDD333UUUDDDDDDDDDDDDDDDUUUDDDUUUfffUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUfffUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDD333DDDDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDDDDDDDfffUUUDDDDDDDDDUUUUUUUUUfffDDDUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDffffffUUUUUUUUUfffUUUfffDDDDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUDDD333UUUDDDDDDDDDDDDDDDUUUDDDUUUfffUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUfffUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDD333DDDDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDDDDDDDfffUUUDDDDDDDDDUUUUUUUUUfffDDDUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDffffffUUUUUUUUUfffUUUfffDDDDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUDDD333UUUDDDDDDDDDDDDDDDUUUDDDUUUfffUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUfffUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUDDDDDDffffffDDDDDD333DDDUUUDDDUUUUUUDDDUUUDDD333333333333UUUUUUUUUUUUDDDUUUfffUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDUUU333UUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUDDDDDDDDDUUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUfffUUUfffUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUfffUUUUUUUUUDDD333DDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUDDDDDDffffffDDDDDD333DDDUUUDDDUUUUUUDDDUUUDDD333333333333UUUUUUUUUUUUDDDUUUfffUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDUUU333UUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUDDDDDDDDDUUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUfffUUUfffUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUfffUUUUUUUUUDDD333DDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUDDDDDDffffffDDDDDD333DDDUUUDDDUUUUUUDDDUUUDDD333333333333UUUUUUUUUUUUDDDUUUfffUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDUUU333UUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUffffffDDDDDDDDDUUUfffUUUUUUUUUUUUUUUDDDUUU333DDDDDDUUUUUUDDDDDDDDD333333333DDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDhhhYYYfffUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUffffffUUUDDD333UUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUffffffUUUffffffDDDDDDDDDUUUfffUUUUUUUUUUUUUUUDDDUUU333DDDDDDUUUUUUDDDDDDDDD333333333YYYDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDfffUUUUUUUUUDDDDDDDDDDDDDDDDDDzzzDDDUUUUUUffffffUUUDDD333UUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUffffffUUUffffffDDDDDDDDDUUUfffUUUUUUUUUUUUUUUDDDUUU333DDDDDDUUUUUUDDDDDDDDD333333333DDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDwwwUUUUUUUUUUUUUUUUUUUUUDDD333UUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUŽŽŽ   ÁÁÁìììÿÿÿŽŽŽDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUwwwUUUUUUDDDDDDDDDfffUUUDDDDDDfffUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUUUUDDDwwwUUUUUUUUUUUUUUUUUUUUUDDD333UUUDDDUUUDDDDDD‚‚‚‚‚‚»»»ÕÕÕÿÿÿÁÁÁUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDmmm‚‚‚ÆÆÆÙÙÙÿÿÿÆÆÆUUUUUUwwwUUUUUUDDDDDDDDDfffUUUDDDDDDfffUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUUUUDDDwwwUUUUUUUUUUUUUUUUUUUUUDDD333UUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDfffUUUUUUUUUfffUUUfffUUUUUUUUUUUUDDDfffUUUUUU333DDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUfffUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUfffDDDUUUDDDUUUDDDfffUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUhhh™™™ŽŽŽÆÆÆÿÿÿÿÿÿDDDDDDUUUUUUUUU333DDDzzzzzzUUUUUUUUUfffUUUfffUUUDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDUUU333UUUfffmmmˆˆˆDDDDDDUUUfffUUUfffDDDUUUDDDUUUUUUfffUUUUUUUUUfffUUUfffUUUUUUUUUUUUDDDfffUUUUUU333DDDDDDDDDDDDUUUYYY‚‚‚‚‚‚«««ÿÿÿÿÿÿ³³³DDDDDDDDDDDDUUUDDDUUUfffUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUfffDDDUUUDDDUUUDDDfffUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUUUUUUUDDDDDDDDDUUUUUUUUU333‚‚‚ŽŽŽ   ÿÿÿÿÿÿŽŽŽfffUUUfffUUUDDDUUUhhhŽŽŽUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDUUU333UUUfffDDDfffDDDDDDUUUfffUUUfffDDDUUUDDDUUUUUUfffUUUUUUUUUfffUUUfffUUUUUUUUUUUUDDDfffUUUUUU333DDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUfffUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUfffDDDUUUDDDUUUDDDfffUUUDDDDDDUUUfffUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUDDDDDDUUUffffffUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUDDDDDDDDDUUUDDDUUUDDD333DDDDDDDDDUUUUUUDDDDDDDDDUUU333‚‚‚ÿÿÿÿÿÿ333UUUDDDUUUDDDDDDmmmÿÿÿÿÿÿUUUUUUUUUDDDUUUDDDDDDUUU333UUUDDDDDD333DDDUUUDDDUUUDDDDDDUUUUUUUUUUUUfffzzzÿÿÿÿÿÿ333DDDDDDUUUDDDUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDŽŽŽÿÿÿÿÿÿ™™™UUUDDDDDDUUUffffffUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUDDDDDDDDDUUUDDDUUUDDD333DDDDDDDDDUUUUUUDDDDDDDDDUUU333DDD333UUU333UUUDDDUUUDDDDDDDDDDDDUUUÿÿÿÿÿÿŽŽŽDDDUUUDDDDDDUUU333ìììÿÿÿ‚‚‚333DDDUUUDDDUUUDDDDDDUUUUUUUUUUUUfffUUUUUUDDD333DDDDDDUUUDDDUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUDDDDDDUUUffffffUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUDDDDDDDDDUUUDDDfffUUUDDDUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUfffUUUUUUDDDDDDUUUUUUUUUfffDDDDDDDDDUUUfff333DDDUUUDDDDDDUUU333UUUDDDUUUUUUDDDUUUDDDDDDDDDDDDfffUUUUUUUUUUUUDDDfffUUU333DDDDDD333UUUDDDUUUDDDUUUDDDUUUDDDUUU333‚‚‚ÿÿÿÆÆÆDDDDDDUUUUUUUUUDDD‚‚‚ÿÿÿÿÿÿUUUUUUDDDDDDDDDDDDfff333DDDDDDDDDDDDDDDUUUUUUUUUfffUUUDDDUUUUUUDDDDDDDDDŽŽŽÿÿÿÿÿÿ333UUUUUUUUUUUUfffUUUUUUUUUfffffffffUUUDDDUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUŽŽŽÿÿÿÿÿÿzzzDDDDDDUUUUUUUUUfffDDDDDDDDDUUUfff333DDDUUUDDDDDDUUU333UUUDDDUUUUUUDDDUUUDDDDDDDDDDDDfffUUUUUUUUUUUUDDDfffUUU333DDDDDD333UUUDDDUUUDDDUUUDDDUUUDDDUUU333DDDDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUÿÿÿÿÿÿDDDDDDDDDDDDfff333DDDÿÿÿÿÿÿ‚‚‚DDDUUUUUUUUUfffUUUDDDUUUUUUDDDDDDDDDUUUDDDDDD333UUUUUUUUUUUUfffUUUUUUUUUfffffffffUUUDDDUUUDDDDDD333DDDDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUfffUUUUUUDDDDDDUUUUUUUUUfffDDDDDDDDDUUUfff333DDDUUUDDDDDDUUU333UUUDDDUUUUUUDDDUUUDDDDDDDDDDDDfffUUUUUUUUUUUUDDDfffUUU333UUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDUUU333UUUDDDDDD¤¤¤ÿÿÿÁÁÁ333333UUUUUUDDDUUUhhhÁÁÁŽŽŽUUUDDDDDDUUUDDDUUUfffUUUUUUDDDfffDDDDDDUUUffffffUUUDDDDDDUUUUUUDDDUUUUUUhhhÁÁÁŽŽŽfffUUUUUUUUUUUUDDDUUUDDDUUUUUUfffUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDŽŽŽÿÿÿÿÿÿDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDUUU333UUUDDDDDD333DDDDDD333333UUUUUUDDDUUUUUUDDDzzzÿÿÿÿÿÿDDDUUUDDDUUUfffUUUUUU«««»»»DDDDDDUUUffffffUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUUUUfffUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDD333UUUUUUUUUfffUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUfffUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDD333fffUUUfffUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDD333333UUUDDDUUUUUUUUUDDDDDDDDDDDDDDDÁÁÁÿÿÿ‚‚‚DDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUfffDDDDDDUUUfffUUUUUUUUUDDDUUUDDDUUUUUUDDDUUUfffUUUUUUDDDUUUYYY»»»ŽŽŽDDDUUUDDDUUUDDD333UUUUUUUUUfffUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUfffUUUUUU™™™ÿÿÿêêêUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDD333fffUUUfffUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDD333333UUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUŽŽŽÿÿÿÁÁÁDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUfffDDDDDDUUUfffUUUUUUUUUDDDUUUDDDUUUUUUDDDUUUfffUUUUUUDDDUUUDDDfffUUUDDDUUUDDDUUUDDD333UUUUUUUUUfffUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUfffUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDD333fffUUUfffUUUDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDD333DDDDDDDDD333UUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDfffUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDD333DDDDDDDDDDDDÁÁÁÿÿÿ‚‚‚UUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUDDDDDDDDDDDDUUU333DDD333fffDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUUUUDDD«««ÿÿÿÿÿÿDDD333DDDDDDDDD333UUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDfffUUUUUU‚‚‚ÿÿÿÁÁÁUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDD333DDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUŽŽŽÿÿÿÆÆÆfffUUUUUUDDDDDDDDDDDDUUU333DDD333fffDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDD333DDDDDDDDD333UUUUUUUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDfffUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUfffUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDDDD333UUUUUU333UUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUfffUUUUUUUUUUUU333DDDUUUUUUDDDUUUUUUUUUUUU333UUUDDDUUUUUUUUUUUUDDDUUUUUUffffffDDDfffDDDDDDUUUUUUDDDUUUfffDDDUUUDDDfffDDDUUUDDD333UUUDDD333DDDDDDÿÿÿÿÿÿUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUU333333DDDDDDUUUDDDDDDUUUDDDUUUUUUfffDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDÁÁÁÿÿÿîîîUUUDDDDDDDDDDDDDDDUUUDDDDDD333UUUUUU333UUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUU³³³ÿÿÿÁÁÁUUUUUUUUUfffUUUUUUUUUUUU333DDDUUUUUUDDDUUUUUUUUUUUU333UUUDDDUUUUUUUUUUUUDDDUUUUUUffffffDDDfffDDDDDDUUUUUUDDDUUUfffDDDUUUDDDfffDDDUUUDDD333UUUDDD333DDDDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUÁÁÁÿÿÿŽŽŽUUUUUUUUUUUUDDDUUUUUU333333DDDDDDUUUDDDDDDUUUDDDUUUUUUfffDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUfffUUUDDDDDDDDDDDDDDDUUUDDDDDD333UUUUUU333UUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUfffUUUUUUUUUUUU333DDDUUUUUUDDDUUUUUUUUUUUU333UUUDDDUUUUUUUUUUUUDDDUUUUUUffffffDDDfffDDDDDDUUUUUUDDDUUUfffDDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUU333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUfffUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUU333DDDDDDUUUDDDDDDfffDDDUUUfffUUUDDDDDDfffDDDUUUDDDUUU333UUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333DDDDDDDDDDDDDDDÿÿÿÿÿÿDDDDDDUUUUUUUUUfffUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUU333UUUUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUfffDDDUUUÆÆÆÿÿÿÆÆÆ333DDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUU333DDDDDDDDDUUUUUUUUUUUUDDDÆÆÆÿÿÿŽŽŽfffUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUU333DDDDDDUUUDDDDDDfffDDDUUUfffUUUDDDDDDfffDDDUUUDDDUUU333UUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUfffUUUDDDUUUÁÁÁÿÿÿŽŽŽUUUDDDUUUDDDUUUUUUUUU333UUUUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUfffDDDUUUUUUUUUUUU333DDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUU333DDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUfffUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUU333DDDDDDUUUDDDDDDfffDDDUUUfffUUUDDDDDDfffDDDUUUDDDUUU333UUUDDDDDDDDDUUUDDD333DDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUffffffDDDUUUUUUDDDUUUDDDUUU333333DDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDhhhÿÿÿÙÙÙUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUfffDDDUUUUUUDDDUUUUUU333DDDUUUUUUfffUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUÆÆÆÿÿÿ   333DDDUUUDDD333DDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUYYYDDDUUUDDDUUUUUUDDDÁÁÁÿÿÿ™™™fffDDDUUUUUUDDDUUUDDDUUU333333DDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUhhhfffUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDÙÙÙÿÿÿwwwDDDUUUUUUDDDUUUUUU333DDDUUUUUUfffUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUU333DDDUUUDDD333DDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUffffffDDDUUUUUUDDDUUUDDDUUU333333DDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDfffUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDD333DDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUDDDDDDDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDmmm«««ÆÆÆÁÁÁÿÿÿÿÿÿÁÁÁDDDDDDUUUDDDDDDDDDmmm———ÆÆÆ«««UUUDDDUUUUUUDDDDDDDDDDDDDDDUUUUUUzzzÆÆÆÆÆÆÆÆÆÿÿÿÆÆÆÝÝÝ   UUUDDDDDDDDDzzz———ÁÁÁ«««DDDDDDDDDUUUUUUDDDUUUÆÆÆÿÿÿ‚‚‚DDDDDDUUUUUUDDDfffUUUUUUDDDDDDDDDhhh«««ÁÁÁÁÁÁÿÿÿÁÁÁÿÿÿ```DDDDDDDDDDDDUUUDDDÙÙÙÿÿÿUUUDDDDDDUUUUUUDDDDDDDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDD———»»»ÆÆÆêêêÕÕÕèèè«««UUUDDDDDDDDDUUUDDD‚‚‚———ÁÁÁŽŽŽDDDUUUDDDDDDDDDYYY‚‚‚ÁÁÁ«««DDDUUUDDDUUUDDDDDDDDDDDDUUUDDDYYY««««««ÁÁÁìììÿÿÿÿÿÿDDDUUUUUUDDDDDDDDDYYY‚‚‚ÆÆÆÙÙÙUUUUUUUUUUUUUUUUUUfffUUUUUUDDD———ÁÁÁÆÆÆÕÕÕÿÿÿ«««YYYDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDfffUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDDDD333DDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUDDDDDDDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDfffUUUfffDDDDDDDDDUUUUUUDDDUUUDDDUUUDDD333DDDDDDDDDDDDDDDUUUffffffUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDD333DDD333DDD333DDDUUUDDDDDDDDDUUUUUUDDDUUUUUUUUU333DDDDDDDDDfffDDDUUUDDDDDDDDDUUUUUUÁÁÁ———UUUDDDUUUÁÁÁÿÿÿ———DDDUUUUUUDDD———»»»ÕÕÕÿÿÿÿÿÿŽŽŽDDDDDDDDDDDDDDDUUUDDDDDDfffhhhÕÕÕ³³³UUUUUUUUU   ÿÿÿÿÿÿzzzDDDUUU———ÆÆÆÕÕÕÿÿÿÿÿÿŽŽŽUUUUUUUUUfffYYYÁÁÁÆÆÆÿÿÿÿÿÿÙÙÙÁÁÁÆÆÆÆÆÆYYYfffUUUfffDDDDDDDDDŽŽŽ³³³YYYUUUDDD   ÿÿÿÿÿÿDDDDDDDDDDDDDDDUUUfffÿÿÿÿÿÿUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDD333DDDIIIÁÁÁ```DDDUUUYYYÿÿÿÿÿÿŽŽŽUUUDDDUUUUUU   »»»êêêÿÿÿÿÿÿˆˆˆDDDUUUDDDmmmÁÁÁÆÆÆÿÿÿÿÿÿÁÁÁUUUDDDUUUDDDUUUDDDDDDUUUUUU‚‚‚ÁÁÁIIIDDDUUUŽŽŽÿÿÿÕÕÕDDDDDDDDDDDDzzzÁÁÁÁÁÁÿÿÿÿÿÿÁÁÁUUUUUUUUUUUUUUUUUUfffUUUmmmììì‚‚‚UUUDDD333ŽŽŽÿÿÿìììhhhUUUfffDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDfffUUUfffDDDDDDDDDUUUUUUDDDUUUDDDUUUDDD333DDDDDDDDDDDDDDDUUUffffffUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDD333DDD333DDD333DDDUUUDDDDDDDDDUUUUUUDDDUUUUUUUUU333DDDDDDDDDfffDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUfffDDDUUUUUUUUUUUU333DDDUUUUUUDDDDDDDDDDDDDDD333333333DDDDDD333DDD333DDDDDDDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDYYYèèè‚‚‚UUUUUUUUUDDDÁÁÁÿÿÿ‚‚‚333DDDDDDDDDDDDDDDDDDÿÿÿÿÿÿmmmUUUUUUUUUUUUUUUUUUffffffhhhììì™™™UUUUUUUUUUUUŽŽŽÿÿÿÿÿÿfffDDDDDDUUUUUUUUUÿÿÿÿÿÿmmmDDDDDDUUUUUUUUUffffffÿÿÿÿÿÿUUUDDDDDDDDDUUUDDDUUUDDDDDDDDDÆÆÆÆÆÆDDDDDDUUUDDDŽŽŽÿÿÿÁÁÁDDDUUUDDDUUUfffDDDUUUÿÿÿÙÙÙUUU333DDDUUUUUUDDDDDDDDDDDDDDD333333333DDDDDD333DDD333DDD‚‚‚êêêYYYUUUUUUDDDDDDÿÿÿÿÿÿUUUUUUUUUDDDDDDDDDDDD‚‚‚ÿÿÿÿÿÿDDDDDDUUUDDDDDDDDDDDDÿÿÿÿÿÿŽŽŽUUUUUUDDDDDD333DDD333DDDÁÁÁÁÁÁDDDDDDDDDUUU‚‚‚ÿÿÿÆÆÆUUUUUUUUUUUUUUUffffffÆÆÆÿÿÿ»»»UUUUUUUUUUUUUUUfffUUUˆˆˆÿÿÿ‚‚‚UUUUUUUUUDDDUUUÕÕÕÿÿÿ«««UUUUUUUUUffffffUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUfffDDDUUUUUUUUUUUU333DDDUUUUUUDDDDDDDDDDDDDDD333333333DDDDDD333DDD333DDDDDDDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUfffDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDD333UUU333333"""DDD333UUUDDDDDDDDDDDD333DDD333UUUUUUUUUDDDUUUUUUUUUUUUUUU333UUU333333DDDUUUDDDDDDUUUDDDUUUDDDDDDDDDêêê   DDDUUUUUUUUUUUUÆÆÆÿÿÿ```DDDUUUDDD333DDDDDD333ÿÿÿÿÿÿDDDfffUUUUUUUUUUUUffffffhhhììì   UUUUUUUUUUUUUUUŽŽŽÿÿÿÆÆÆUUUDDDUUUUUUUUU333ÿÿÿÿÿÿDDDUUUDDDffffffUUUUUUUUUÿÿÿîîîDDDUUUUUUDDDUUUDDDUUUDDDDDDÁÁÁÙÙÙDDDDDDUUUDDDUUUÆÆÆÿÿÿ———DDDUUUUUUfffDDDDDDzzzÿÿÿÁÁÁDDDDDDDDDUUUDDDDDD333UUU333333"""DDD333UUUDDDDDDDDDDDDwwwÿÿÿIIIUUUUUUUUUDDDŽŽŽÿÿÿÙÙÙUUUUUU333UUU333333DDDŽŽŽÿÿÿêêêUUUDDDUUUDDDDDDDDDDDDÿÿÿÿÿÿŽŽŽUUUUUUUUUUUUDDD333DDD³³³ÕÕÕ333DDDDDD333DDD‚‚‚ÿÿÿ»»»UUUUUUUUUUUUffffffUUUÆÆÆÿÿÿŽŽŽUUUUUUUUUUUUUUUfffUUUììì«««UUUUUUUUU333DDDUUU«««ÿÿÿêêêffffffUUUUUUUUUUUUfffDDDUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUfffDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDD333UUU333333"""DDD333UUUDDDDDDDDDDDD333DDD333UUUUUUUUUDDDUUUUUUUUUUUUUUU333UUU333333DDDUUUDDDDDDUUUUUUUUUDDDUUUDDDDDD333DDDUUU333UUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUU333DDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUDDD333ÆÆÆêêêDDDUUUfffDDDDDDUUUèèèÿÿÿDDDDDDUUUDDDUUUUUU333DDDÿÿÿìììfffUUUDDDUUUDDDDDDUUUUUUÕÕÕÕÕÕDDD333DDDUUUUUUUUUÆÆÆÿÿÿ«««UUUUUUDDDDDDDDDUUUÿÿÿêêêDDDUUUUUUUUUUUUUUUUUUhhhÿÿÿÁÁÁUUUUUUUUUUUUDDDUUUDDDDDDÿÿÿhhh333UUUfffUUUUUUÆÆÆÿÿÿŽŽŽUUUDDDUUUDDDDDDfffŽŽŽÿÿÿÆÆÆUUUDDDUUUUUUUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUU333DDDYYYÿÿÿDDDDDDDDDDDDUUUŽŽŽÿÿÿÁÁÁDDD333UUUDDDDDDUUUDDDŽŽŽÿÿÿÁÁÁDDDUUUUUUDDD333UUUDDDÿÿÿÿÿÿfffDDDDDDUUU333DDDDDD‚‚‚ÿÿÿmmmUUUUUU333DDDfff³³³ÿÿÿŽŽŽDDDUUUDDDDDDUUUUUUDDDÁÁÁÿÿÿ```DDDUUUUUUUUUUUUUUU«««ÿÿÿzzzDDDDDDDDDUUUUUUDDD‚‚‚ÿÿÿÿÿÿUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDD333DDDUUU333UUUfffUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUU333DDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUUUU333UUUDDDDDD333DDDUUUUUUUUUfffDDDDDDUUUDDDfffUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDD333DDD333DDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDmmmÿÿÿ   UUUUUUUUUDDDDDDDDDÿÿÿÿÿÿDDDDDDDDDDDDDDDUUU333mmmÿÿÿÆÆÆfffUUUUUUUUUDDDUUUUUU———ÿÿÿzzzDDDDDDDDDffffffUUUÆÆÆÿÿÿ‚‚‚DDDDDDDDDUUUUUUmmmÿÿÿÌÌÌUUUUUUDDDfffUUUUUUDDDŽŽŽÿÿÿÁÁÁfffDDDUUUDDDUUUDDDUUUYYYÿÿÿ«««DDDUUUfffUUUUUUUUUÿÿÿÿÿÿDDDDDD333DDDUUUUUUUUU™™™ÿÿÿ‚‚‚UUUDDDfffUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDÕÕÕèèèDDD333DDDDDDUUUDDDÆÆÆÿÿÿ‚‚‚DDDDDDUUUDDDDDDUUUDDDÁÁÁÿÿÿ———DDDDDDDDDDDDDDDUUUUUUÿÿÿÿÿÿUUUDDDDDDDDDDDDDDDDDDêêêÕÕÕDDDDDDUUU333DDDUUUÆÆÆÿÿÿŽŽŽUUUUUUDDDUUUUUUDDDDDDìììÿÿÿDDDDDDffffffUUUUUUUUUÿÿÿÕÕÕDDDDDDUUUUUUDDDUUUfffŽŽŽÿÿÿÿÿÿfffUUUUUUDDDUUUUUUDDDfffDDDUUUDDDUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUUUU333UUUDDDDDD333DDDUUUUUUUUUfffDDDDDDUUUDDDfffUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDD333DDD333DDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDfffUUUDDDDDDUUUDDDUUUUUUfffUUUDDD333333DDDUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDfffUUUUUUDDDDDDDDDUUUUUU333333DDDDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDÕÕÕÿÿÿDDDDDDUUUDDDUUU333DDDÿÿÿÁÁÁDDDDDDUUUDDDUUUDDDDDDŽŽŽÿÿÿ»»»DDDUUUDDDUUUDDDDDDDDDìììÕÕÕ333DDDDDDUUUDDDUUUDDDÿÿÿÿÿÿYYYDDDUUUUUUUUUUUU‚‚‚ÿÿÿ«««DDDDDDDDDUUUUUUUUUUUU™™™ÿÿÿ™™™UUUDDDDDDfffUUUDDDDDDÙÙÙÿÿÿhhhUUUfffUUUDDD333333ÿÿÿÿÿÿUUUDDDUUUDDDUUUDDDDDD³³³ÿÿÿ™™™UUUUUUDDDDDDDDDUUUUUU333333DDDDDDDDD333UUUDDDDDD———ÿÿÿ   UUUDDDDDDUUUUUUDDDÁÁÁÿÿÿwwwDDDUUUDDDDDDUUUUUUDDDÁÁÁÿÿÿ‚‚‚UUUDDDUUUDDDDDDUUUDDDÿÿÿÙÙÙDDDUUU333DDDDDDDDD———ÿÿÿŽŽŽDDDUUUDDDDDDUUUUUUÌÌÌÿÿÿUUUDDDUUUDDDDDDDDDUUUDDDÿÿÿêêêDDDUUUDDDUUUDDDUUU———ÿÿÿ«««UUUUUUUUUUUUDDDUUUDDD‚‚‚ÿÿÿÿÿÿUUUUUUUUUUUUfffUUUfffUUUDDDDDDfffUUUDDDDDDUUUDDDUUUUUUfffUUUDDD333333DDDUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDfffUUUUUUDDDDDDDDDUUUUUU333333DDDDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUDDDUUUfffUUUUUUDDDDDDUUU333DDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUfffDDD333DDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDmmmÿÿÿÁÁÁUUUUUUDDDUUUDDDDDD‚‚‚ÿÿÿÁÁÁUUUUUUUUU333UUU333DDD‚‚‚ÿÿÿŽŽŽUUUUUUUUUDDDDDDUUU———ÿÿÿ———DDDDDDUUUUUUUUUDDDDDDÿÿÿÿÿÿDDDUUUUUUUUUUUUfff‚‚‚ÿÿÿ‚‚‚DDDDDDDDDDDDDDDDDDUUU³³³ÿÿÿ‚‚‚UUUDDDUUUUUUDDDDDDhhhÿÿÿÙÙÙfffUUUUUUDDDDDDUUUwwwÿÿÿÆÆÆDDDDDDUUUUUUUUUUUUUUUÆÆÆÿÿÿzzzDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDÕÕÕÿÿÿYYYDDDDDDUUUfffDDD333ÿÿÿÿÿÿDDDUUUDDDDDDUUUUUUDDDDDDÙÙÙÿÿÿYYYDDDDDDDDDDDDUUUDDDŽŽŽÿÿÿÁÁÁUUUDDDDDDDDDDDDDDDìììÿÿÿUUU333UUU333DDDDDDUUUÿÿÿÿÿÿUUUUUUDDDDDDUUUDDDDDDDDDÿÿÿÁÁÁUUUUUUUUUDDDDDDUUUÁÁÁÿÿÿŽŽŽUUUUUUUUUfffDDDUUUDDD‚‚‚ÿÿÿÕÕÕDDDDDDDDDUUUUUUfffDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUfffUUUUUUDDDDDDUUU333DDDUUUDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUfffDDD333DDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDD333DDDDDD333DDD333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333333DDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUfffUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDfff³³³ÿÿÿŽŽŽDDDDDDDDDDDDDDD333‚‚‚ÿÿÿ³³³DDDUUUDDDDDDDDDDDDUUUÆÆÆÿÿÿŽŽŽUUUDDDUUUDDDDDDUUUÕÕÕÿÿÿYYYUUUDDDUUUDDDDDDUUU‚‚‚ÿÿÿÙÙÙUUUDDDUUUDDDDDDDDDÁÁÁÿÿÿ‚‚‚DDDDDDUUUUUUUUUUUUUUUÁÁÁÿÿÿmmmDDDDDD333DDDDDD333«««ÿÿÿ———DDDUUUDDDDDDDDDDDD‚‚‚ÿÿÿÁÁÁUUUDDDDDDUUUDDDUUUUUUÆÆÆÿÿÿDDDDDDDDDDDDDDDDDDDDDDDD333333DDDDDDDDDDDDDDDUUUmmmÿÿÿÕÕÕDDDDDDUUUUUUDDDUUUDDDÿÿÿÿÿÿUUUfffUUUUUUDDDDDDUUUUUUÿÿÿÿÿÿUUUUUUDDDfffUUUDDDUUU‚‚‚ÿÿÿ«««DDDDDD333DDDDDDzzzÿÿÿÆÆÆDDDDDDDDDDDDUUUUUUDDDÿÿÿìììDDDUUUDDDDDDUUUDDDUUU‚‚‚ÿÿÿÁÁÁUUUDDDDDDUUUDDDUUUÿÿÿÿÿÿmmmUUUDDDDDDDDDDDD333DDD‚‚‚ÿÿÿÆÆÆUUUUUUUUUUUUDDDDDDDDDDDDDDD333DDDDDD333DDD333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333333DDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUfffUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDD333DDDDDDDDDUUUDDDUUUUUUDDDDDD333UUUDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDfffUUUDDDDDDDDDDDDDDD333333DDDUUU333DDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUUUUffffffUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUìììÿÿÿYYYDDD333DDDDDD333DDDÁÁÁÿÿÿŽŽŽUUUDDDDDDDDDDDDUUUDDDÆÆÆÿÿÿUUUDDDUUUDDDDDDDDDYYYÿÿÿêêêUUUfffUUUUUU333UUUDDD———ÿÿÿÆÆÆDDDDDDDDDUUUUUUUUU»»»ÿÿÿDDDDDDDDDUUUUUUUUUUUUfffÕÕÕÿÿÿDDDUUUDDDDDDDDDDDD333ÕÕÕÿÿÿmmmUUUDDDUUUUUUDDDDDD»»»ÿÿÿ———UUUUUUDDDDDDDDDUUUDDDÿÿÿÿÿÿDDDfffUUUDDDDDDDDDDDDDDD333333DDDUUU333DDDDDDDDD———ÿÿÿ«««DDD333UUUDDDDDD333‚‚‚ÿÿÿÙÙÙffffffUUUDDDDDDDDDDDDUUUÿÿÿÕÕÕUUUUUUUUUUUUUUUUUUDDD«««ÿÿÿ‚‚‚DDD333DDDDDDDDD³³³ÿÿÿ———DDDDDDDDDUUUDDDUUUŽŽŽÿÿÿÁÁÁUUUDDDDDDDDDDDDDDDDDDŽŽŽÿÿÿŽŽŽUUU333UUUDDDDDDDDDÿÿÿÿÿÿDDDDDDUUUUUUUUU333333DDDÁÁÁÿÿÿ   UUUUUUUUUfffDDDDDDDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUDDDUUUUUUDDDDDD333UUUDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDfffUUUDDDDDDDDDDDDDDD333333DDDUUU333DDDDDDDDDDDDDDDDDDDDD333UUUDDDDDD333DDDUUUUUUffffffUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDD333DDDUUUDDDDDDDDDDDDDDD333DDD333DDDDDDUUUDDDfffDDDDDDDDDDDDDDDUUUDDD333DDDUUUDDDDDDDDD333333DDDUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDYYYÿÿÿÿÿÿDDDDDDDDDDDDDDDUUUUUUÕÕÕÿÿÿ‚‚‚DDDDDDDDDDDDDDDDDDfffêêêÿÿÿDDDDDDDDDDDDDDD333———ÿÿÿÆÆÆUUUDDDDDDDDDDDDUUUfffÆÆÆÿÿÿ³³³UUUDDDUUUDDDUUUDDDèèèÿÿÿDDDUUUUUUfffUUUUUUUUUfffÿÿÿÿÿÿUUUDDDDDDDDDDDDDDDYYYÿÿÿÿÿÿUUUDDDDDDDDDDDDDDD333ÕÕÕÿÿÿ‚‚‚DDDUUUDDDfffDDDDDDDDDÿÿÿÿÿÿUUUDDD333DDDUUUDDDDDDDDD333333DDDUUUDDD333DDDUUUÕÕÕÿÿÿ‚‚‚DDDDDDDDDDDDDDDDDD   ÿÿÿÆÆÆUUUUUUDDDUUUUUUUUUUUUzzzÿÿÿÆÆÆUUUDDDDDDDDDDDDDDDDDDÕÕÕÿÿÿ‚‚‚DDDUUUUUUDDDUUUÕÕÕÿÿÿ‚‚‚DDDDDDDDDDDDfffDDD   ÿÿÿÁÁÁDDDDDDDDD333DDDUUUUUU³³³ÿÿÿ‚‚‚DDDDDDUUUfffUUUŽŽŽÿÿÿÿÿÿDDDUUUDDDUUUDDD333DDDDDDÆÆÆÿÿÿwwwUUUUUUUUUfff333DDDUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDDDDDDDDDD333DDD333DDDDDDUUUDDDfffDDDDDDDDDDDDDDDUUUDDD333DDDUUUDDDDDDDDD333333DDDUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDD333333UUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUDDD333DDD333DDDDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDfffUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDD‚‚‚ÿÿÿÑÑÑUUUUUUDDDDDDUUU333YYYÿÿÿÿÿÿmmm333DDDUUUDDDDDDUUUUUUÿÿÿêêêDDDDDDUUUDDDDDDDDDÌÌÌÿÿÿ³³³DDDUUUDDDDDDDDDUUUUUUÿÿÿÿÿÿ‚‚‚DDDUUUUUUfffUUUDDDÿÿÿêêêDDDUUUUUUUUUUUUUUUUUUUUUÿÿÿìììDDDUUU333DDDDDDDDDwwwÿÿÿÙÙÙUUUDDDDDDUUUUUUDDDDDDÿÿÿÿÿÿŽŽŽDDDUUUUUUDDDUUUDDDzzzÿÿÿÁÁÁDDDDDDDDDUUUDDD333DDD333DDDDDDDDDUUU333DDD333DDDÿÿÿÿÿÿYYYDDDDDDUUUDDDUUUDDDÆÆÆÿÿÿÁÁÁfffUUUDDDUUUUUUDDDUUUŽŽŽÿÿÿÆÆÆDDDDDDDDDDDDDDD333hhhÿÿÿÿÿÿmmmUUU333DDDDDDDDDÿÿÿÿÿÿYYYUUUDDDDDDUUUUUUUUUÕÕÕÿÿÿ«««UUUDDDDDDDDDfffDDDUUUÁÁÁÿÿÿmmmDDDDDDUUUUUUDDDŽŽŽÿÿÿÿÿÿUUUUUUfffUUUDDDDDDDDDDDDÿÿÿÙÙÙUUUUUUUUUUUUUUUDDDUUUDDDUUU333DDDDDDDDD333333UUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUDDD333DDD333DDDDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDfffUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDDDD333333UUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDD333333DDDDDDDDDDDDDDDfffDDDUUUUUUDDD333DDDUUUUUUDDDUUUDDDUUUUUU———ÿÿÿÁÁÁDDDUUUDDDUUUDDDUUU   ÿÿÿÿÿÿDDDUUUDDDUUUDDDDDDUUUhhhÿÿÿÁÁÁUUUUUUUUUUUUUUUUUUÕÕÕÿÿÿwwwDDDUUU333333DDDUUU———ÿÿÿÿÿÿ‚‚‚UUUDDDDDDDDD333YYYÿÿÿ»»»UUUDDDUUUUUUUUUDDDDDD‚‚‚ÿÿÿÁÁÁDDDUUUDDDDDDDDDUUU———ÿÿÿÆÆÆUUUDDDUUUDDDUUUDDD———ÿÿÿÿÿÿUUUUUUUUUDDDUUUDDDUUUŽŽŽÿÿÿÁÁÁUUUDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDDDDUUUYYYÿÿÿÿÿÿDDDDDD333333DDDDDDYYYÿÿÿÿÿÿ™™™DDDUUUUUUDDD333DDDUUU³³³ÿÿÿŽŽŽDDDUUUUUUDDDDDDDDDÁÁÁÿÿÿÿÿÿUUUDDDUUUUUUUUUhhhÿÿÿÿÿÿDDDUUUDDDDDDUUUUUUhhhÿÿÿÿÿÿŽŽŽUUUUUUUUUUUUDDDUUU333ÕÕÕÿÿÿ333333DDDUUUDDDDDD‚‚‚ÿÿÿÿÿÿDDDDDDDDD333DDDDDD333zzzÿÿÿ   UUUUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDDDD333333UUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDUUU333DDD333DDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDD333333DDDDDDDDDDDDDDDfffDDDUUUUUUDDD333DDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDD333333DDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDD333UUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDD333333UUUUUUfffUUUDDD333DDDDDDUUUDDDDDDUUUDDDUUUDDDÁÁÁÿÿÿÁÁÁDDDDDDDDDDDDUUUDDDìììÿÿÿÿÿÿUUUDDDDDDUUUDDDDDDDDD‚‚‚ÿÿÿÁÁÁDDDDDDDDDUUUDDDfffÿÿÿÿÿÿ‚‚‚UUUUUUDDDDDDDDDhhhÿÿÿÿÿÿÿÿÿ333DDD333UUUUUU333‚‚‚ÿÿÿ»»»UUUUUUffffffDDDDDDDDD‚‚‚ÿÿÿÆÆÆDDDDDDUUUUUUDDDDDDÁÁÁÿÿÿÁÁÁUUUDDDDDDUUUDDD333èèèÿÿÿÿÿÿUUUUUUDDDDDDDDDUUUDDD‚‚‚ÿÿÿ»»»UUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUU‚‚‚ÿÿÿÿÿÿDDDDDD333DDDDDDDDD¤¤¤ÿÿÿÿÿÿŽŽŽfffUUUDDD333DDDDDDUUUÁÁÁÿÿÿŽŽŽDDDUUUDDDDDDDDD‚‚‚ÁÁÁÿÿÿÿÿÿDDDUUUDDDUUUUUU‚‚‚ÿÿÿÿÿÿDDDUUUDDDDDDDDDDDD«««ÿÿÿÿÿÿ‚‚‚DDDUUUDDDfffDDDDDDDDDÿÿÿÿÿÿDDDDDDDDDUUUDDDDDD‚‚‚ÿÿÿÿÿÿ333UUUUUU333DDDDDD333³³³ìììffffffDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDD333333DDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDD333UUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDD333333UUUUUUfffUUUDDD333DDDDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDUUUfffUUUUUUUUUUUUDDDDDDDDD333UUUUUUUUUDDD333DDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDÁÁÁÿÿÿÁÁÁDDDDDDUUUUUUDDDÆÆÆÆÆÆÿÿÿÿÿÿ333UUUUUUDDDUUUUUUUUU   ÿÿÿÆÆÆUUUDDDUUUDDDUUU333ÿÿÿÿÿÿ‚‚‚UUUUUU333DDDhhhÕÕÕ———ÿÿÿÿÿÿDDDUUUUUUUUUUUU333———ÿÿÿÆÆÆDDDfffUUUfffDDDDDDUUU———ÿÿÿÆÆÆDDDUUUUUUUUUUUUDDDÁÁÁÿÿÿÆÆÆDDDDDDDDD333DDDÁÁÁÁÁÁÿÿÿÿÿÿfffUUUUUUUUUUUUDDDDDD«««ÿÿÿÆÆÆUUUUUUDDD333DDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDD‚‚‚ÿÿÿÿÿÿDDDDDDDDDDDDDDD‚‚‚ÆÆÆÿÿÿÿÿÿŽŽŽDDDDDDDDDUUUUUUUUUUUUÙÙÙÿÿÿ‚‚‚UUUDDDDDDDDDŽŽŽÁÁÁ‚‚‚ÿÿÿÿÿÿUUUDDDUUUUUUDDD‚‚‚ÿÿÿÿÿÿUUUDDDUUUUUUUUUŽŽŽÆÆÆÿÿÿÿÿÿ‚‚‚UUUDDDUUU333UUUDDDYYYÿÿÿÿÿÿ333DDDUUUDDDDDDDDDwwwÿÿÿÿÿÿŽŽŽUUUUUU333DDDDDDhhhÿÿÿˆˆˆUUUfffDDDDDDUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDUUUfffUUUUUUUUUUUUDDDDDDDDD333UUUUUUUUUDDD333DDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUfffUUUDDDDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUU333DDDDDDDDDDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDfffUUUUUUUUUDDD333DDDÁÁÁÿÿÿÕÕÕDDDUUUDDDhhhÆÆÆŽŽŽ‚‚‚ÿÿÿÿÿÿhhhDDD333UUUDDDUUUUUUÆÆÆÿÿÿÕÕÕUUUDDDYYYhhhDDDDDDÿÿÿÿÿÿ———UUUDDDDDDzzzÕÕÕIII———ÿÿÿÁÁÁDDDDDDDDDUUUDDDDDDÆÆÆÿÿÿÕÕÕUUUfffhhhhhhDDDDDDUUUÆÆÆÿÿÿÆÆÆDDDUUUfffUUUfffUUUÁÁÁÿÿÿÙÙÙDDDDDDDDDIIIÁÁÁwww‚‚‚ÿÿÿÿÿÿUUUUUUUUUUUUDDDDDDDDDÁÁÁÿÿÿÆÆÆUUUDDDDDDYYYDDDUUUDDDDDDDDDDDDUUUDDDDDDUUU333‚‚‚ÿÿÿÿÿÿYYYDDD333UUU———ÁÁÁUUUÿÿÿÿÿÿ‚‚‚DDDDDDDDDDDDUUUDDDfffÿÿÿÿÿÿ   DDD333YYYÁÁÁ———DDD‚‚‚ÿÿÿÿÿÿUUUUUUŽŽŽDDDDDDŽŽŽÿÿÿÿÿÿIIIUUUDDDUUU   ÆÆÆUUUÿÿÿÿÿÿ———DDDUUUDDDDDDUUUDDD‚‚‚ÿÿÿÿÿÿYYYUUUDDD```DDD333DDDÿÿÿÿÿÿÁÁÁUUUDDDDDDUUUUUUÕÕÕŽŽŽfffUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUfffUUUfffUUUDDDDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUU333DDDDDDDDDDDDDDD333UUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDfffUUUUUUUUUDDD333UUUDDD333UUUDDDfffUUUDDDUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDD333DDDUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUUUU³³³ÿÿÿÿÿÿÁÁÁŽŽŽ»»»ÙÙÙmmmDDD‚‚‚ÿÿÿÿÿÿÕÕÕÁÁÁÆÆÆ³³³DDDDDDUUUÆÆÆÿÿÿÿÿÿÕÕÕÙÙÙ³³³hhhUUUUUUìììÿÿÿÿÿÿ   ‚‚‚ÁÁÁ«««DDDDDDÆÆÆÿÿÿÆÆÆUUUUUUDDDDDDDDDUUUÁÁÁÿÿÿÿÿÿÝÝÝÙÙÙ«««YYYDDDDDDDDDÁÁÁÿÿÿÿÿÿ   ———ÁÁÁzzzDDD333³³³ÿÿÿÿÿÿÆÆÆ‚‚‚³³³ÙÙÙzzzUUU™™™ÿÿÿÿÿÿÙÙÙÆÆÆ³³³DDD333DDDUUUÆÆÆÿÿÿÿÿÿ   ———ÕÕÕ   UUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDmmmÿÿÿÿÿÿêêê‚‚‚———ÕÕÕ   UUUDDDÿÿÿÿÿÿìììÆÆÆÆÆÆhhhUUUDDDUUUDDDÿÿÿÿÿÿÿÿÿÆÆÆÙÙÙÙÙÙhhhDDDUUU‚‚‚ÿÿÿÿÿÿÙÙÙÕÕÕ———DDDDDDmmmÿÿÿÿÿÿìììŽŽŽ———ÕÕÕ   UUUDDDÿÿÿÿÿÿìììÆÆÆÆÆÆÆÆÆhhhUUUUUUŽŽŽÿÿÿÿÿÿêêêÁÁÁÕÕÕmmmUUUUUUUUU   ÿÿÿÿÿÿ———DDDUUUmmmÆÆÆŽŽŽfffUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDD333UUUDDDfffUUUDDDUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDD333DDDUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDfffffffffDDDDDDUUUUUUDDD333DDDUUUDDDDDDfffUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUDDDUUUUUUDDD333UUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDfffUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUYYYêêêÿÿÿÿÿÿÆÆÆŽŽŽfff333UUUhhhìììÿÿÿÕÕÕ———UUUUUUUUUUUUDDDŽŽŽÿÿÿêêê³³³YYYUUUUUUUUUUUUŽŽŽìììÿÿÿêêê«««YYYUUUDDDUUUÙÙÙÿÿÿŽŽŽUUUUUUUUUUUUUUUDDD‚‚‚ÿÿÿêêê³³³YYYUUUUUUUUUDDDUUUŽŽŽÿÿÿÿÿÿÁÁÁ„„„DDDDDDDDDDDDYYYìììÿÿÿÿÿÿÁÁÁŽŽŽDDDffffffwwwêêêÿÿÿÆÆÆzzzDDD333DDDUUUDDDmmmîîîÿÿÿÕÕÕ———hhhUUUUUUUUUDDDUUUUUUfffUUUDDDUUUUUUDDD333ÆÆÆÿÿÿÿÿÿÕÕÕ   YYYDDDUUUUUUÁÁÁÿÿÿÝÝÝ   UUUDDDUUUUUUUUUDDDÆÆÆÿÿÿÿÿÿÆÆÆmmmUUUDDDDDDUUUzzzÿÿÿììì»»»IIIUUUUUUUUUDDDÁÁÁÿÿÿÿÿÿÙÙÙ   hhhDDDUUUUUUÁÁÁÿÿÿêêê³³³hhhUUUUUUUUUUUUhhhêêêÿÿÿÁÁÁzzzDDDUUUUUUUUUUUUUUU   ìììÿÿÿÿÿÿÕÕÕ———YYYDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDUUUDDD"""DDDDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDfffffffffDDDDDDUUUUUUDDD333DDDUUUDDDDDDfffUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUfffUUUDDDUUUUUUDDD333UUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDfffUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDfffUUUUUUUUUDDDDDDUUUUUUDDDUUUfffUUUDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUDDD333333DDDUUUUUUDDDDDDDDD333DDDUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDÿÿÿÿÿÿhhhUUUUUUUUUDDDUUUUUUUUUfffUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDfffUUUUUUUUUDDDDDDUUUUUUDDDUUUfffUUUDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUDDD333333DDDUUUUUUDDDDDDDDD333DDDUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUfffUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUDDDfffUUUUUUUUUDDDDDDUUUUUUDDDUUUfffUUUDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUDDD333333DDDUUUUUUDDDDDDDDD333DDDUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUfffUUUUUUUUUUUU333DDDDDDUUUUUUUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDD333333UUUDDDUUUDDDDDD333333UUUUUUDDDfffUUUUUUUUUDDDDDDUUUDDDUUUDDDfffUUUfffUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDD333DDDDDDUUUˆˆˆÿÿÿìììUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDDDD333DDDUUU333DDDDDDUUUUUUUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDD333333UUUDDDUUUDDDDDD333333UUUUUUDDDfffUUUUUUUUUDDDDDDUUUDDDUUUDDDfffUUUfffUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDD333DDDDDDUUUfffUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUDDDDDD333DDDUUU333DDDDDDUUUUUUUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDD333333UUUDDDUUUDDDDDD333333UUUUUUDDDfffUUUUUUUUUDDDDDDUUUDDDUUUDDDfffUUUfffUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDD333DDD333333UUUDDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333UUU333UUUUUUDDDUUUDDDfffUUUUUUfffDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDfffUUUfff   ÿÿÿÁÁÁfffDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDUUUUUUUUU333DDDDDD333DDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDD333DDD333333UUUDDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333UUU333UUUUUUDDDUUUDDDfffUUUUUUfffDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDfffUUUfffUUUUUUDDDfffDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUfffUUUUUUDDDUUUUUUUUU333DDDDDD333DDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDD333DDD333333UUUDDDUUUDDDDDDDDD333DDDUUUUUUUUUUUU333UUU333UUUUUUDDDUUUDDDfffUUUUUUfffDDDUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDD333333DDDDDDUUUDDDDDDDDDDDD333333DDDDDDUUUDDDUUU333DDDDDDUUUDDDUUUDDDDDD333UUUffffffUUUUUUDDD333DDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUfffUUU333UUUDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUUUUDDDÕÕÕÿÿÿzzzUUUDDDUUUfffUUUUUUUUUUUUUUUDDDUUUUUUfffUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDD333333DDDDDDUUUDDDDDDDDDDDD333333DDDDDDUUUDDDUUU333DDDDDDUUUDDDUUUDDDDDD333UUUffffffUUUUUUDDD333DDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUfffUUU333UUUDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUfffUUUUUUUUUUUUUUUDDDUUUUUUfffUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDUUUDDD333333DDDDDDUUUDDDDDDDDDDDD333333DDDDDDUUUDDDUUU333DDDDDDUUUDDDUUUDDDDDD333UUUffffffUUUUUUDDDDDDDDDUUUUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUU333333DDDUUUDDDDDDDDD333333DDD333DDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUUUU333UUUfffUUUUUUDDD333333DDD333UUUUUUDDDDDDDDDUUUfffUUUUUUDDDDDDDDDDDDUUUUUUDDDfffDDDDDDUUUUUUDDDDDDUUUDDDDDD333UUUUUUUUUDDDDDDUUUUUUzzzÿÿÿÕÕÕDDD333DDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUU333UUUUUUUUU333DDDUUUUUUUUUDDDDDDUUUUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUU333333DDDUUUDDDDDDDDD333333DDD333DDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUUUU333UUUfffUUUUUUDDD333333DDD333UUUUUUDDDDDDDDDUUUfffUUUUUUDDDDDDDDDDDDUUUUUUDDDfffDDDDDDUUUUUUDDDDDDUUUDDDDDD333UUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDD333DDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUU333UUUUUUUUU333DDDUUUUUUUUUDDDDDDUUUUUUUUUfffUUUDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUU333333DDDUUUDDDDDDDDD333333DDD333DDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUUUU333UUUfffUUUUUUDDD333333UUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDD333DDDDDDDDDDDDDDDDDDDDD333DDDDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUfffUUUUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUU333DDDUUUDDD333UUUDDDDDDDDDDDDUUUUUUUUUÁÁÁêêêYYYDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDD333UUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDD333DDDDDDDDDDDDDDDDDDDDD333DDDDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUfffUUUUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUU333DDDUUUDDD333UUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDD333UUUDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDD333DDDDDDDDDDDDDDDDDDDDD333DDDDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUfffUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUfffDDDUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDD333UUUDDD333UUUUUUDDDUUUDDDfffDDDfffUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDffffffDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD333UUUDDDUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDD‚‚‚ÿÿÿ‚‚‚UUUDDDfffUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDD333DDDDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUfffDDDUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDD333UUUDDD333UUUUUUDDDUUUDDDfffDDDfffUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDffffffDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD333UUUDDDUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDfffUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDD333DDDDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUfffDDDUUUUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDD333UUUDDD333UUUUUUDDDUUUDDDfffDDDfffUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDffffffDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUfffDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUfffDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDD333DDDDDDUUUUUUUUUUUUDDD333UUUUUUUUUDDDUUUUUUUUUfffÁÁÁ   DDDDDDUUUUUU———ììì‚‚‚UUUUUUfffDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDD333DDD333DDDUUUDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUfffDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUfffDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDD333DDDDDDUUUUUUUUUUUUDDD333UUUUUUUUUDDDUUUUUUUUUfffDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDD333DDD333DDDUUUDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUfffDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUfffDDDUUUDDDUUUDDDUUUDDDUUUfffDDDDDDfffUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333UUUUUUUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDfffUUUDDDUUUUUUUUUUUUfffDDDDDD333DDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDÕÕÕÿÿÿìììÆÆÆÌÌÌìììÁÁÁYYYUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUfffDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDUUUfffDDDDDDfffUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333UUUUUUUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDfffUUUDDDUUUUUUUUUUUUfffDDDDDD333DDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUfffUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUfffDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDUUUfffDDDDDDfffUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333UUUUUUUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDfffUUUDDDUUUUUUUUUUUUfffDDDDDDDDDDDDDDDUUUDDDUUUDDDfffDDDDDDUUUDDDUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUUUUUUUUUU333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDD333UUUUUUUUUDDDDDDDDDDDDDDDDDDUUUfffUUUDDDUUUUUUUUUDDD«««ìììÿÿÿêêê³³³mmmDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUfffDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDfffDDDDDDUUUDDDUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUUUUUUUUUU333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDD333UUUUUUUUUDDDDDDDDDDDDDDDDDDUUUfffUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUfffDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDfffDDDDDDUUUDDDUUUDDDDDDDDDDDD333DDDUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUUUUUUUUUU333DDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUDDD333UUUDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDD333UUUUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUffffffDDDDDDUUUUUU333UUU333DDDUUUDDDUUUUUU333UUUDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDDDD333DDDDDDDDDDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUUUUfffUUUDDDDDDUUUfffUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUDDD333UUUDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDD333UUUUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUffffffDDDDDDUUUUUU333UUU333DDDUUUDDDUUUUUU333UUUDDDUUUUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDUUUDDDDDD333DDDDDDDDDDDDDDDDDDUUUUUUDDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDUUUUUUfffUUUDDDDDDUUUfffUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUDDD333UUUDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDD333UUUUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUffffffDDDDDDUUUUUU333UUUDDDUUUDDDfffDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDDDD333333DDDUUUUUUfff333DDDDDDUUUDDD333UUUfffDDD333UUUDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDUUUfffUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUfffUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDDDD333DDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDffffffUUUUUUDDDUUUDDDfffDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDDDD333333DDDUUUUUUfff333DDDDDDUUUDDD333UUUfffDDD333UUUDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDUUUfffUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUfffUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDDDD333DDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDffffffUUUUUUDDDUUUDDDfffDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDDDD333333DDDUUUUUUfff333DDDDDDUUUDDD333UUUfffDDD333UUUDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDUUUfffUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUU333DDDDDDUUUDDDUUUDDDUUUUUU333333UUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUU333DDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUfffUUU333DDDDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUfffUUUUUUUUUfffUUUUUUDDDUUUDDDDDDDDD333UUUUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDfffDDDUUUUUUDDDDDDUUUfffUUUDDDDDDUUUfffDDDDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUU333DDDDDDUUUDDDUUUDDDUUUUUU333333UUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUU333DDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUfffUUU333DDDDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUfffUUUUUUUUUfffUUUUUUDDDUUUDDDDDDDDD333UUUUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDfffDDDUUUUUUDDDDDDUUUfffUUUDDDDDDUUUfffDDDDDDUUUfffUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUU333DDDDDDUUUDDDUUUDDDUUUUUU333333UUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUU333DDDDDDDDDDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUfffUUU333DDDDDDDDDUUUUUUUUUUUU333UUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDD333UUUUUUUUUDDD333DDDDDDDDDDDDUUUUUUDDD333UUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDD333UUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUfffUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUUUUfffDDDUUUUUUffffffDDDDDDUUUDDD333DDD333DDDDDD333DDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUUUU333UUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDD333UUUUUUUUUDDD333DDDDDDDDDDDDUUUUUUDDD333UUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDD333UUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUfffUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUUUUfffDDDUUUUUUffffffDDDDDDUUUDDD333DDD333DDDDDD333DDDUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUUUU333UUUUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDD333UUUUUUUUUDDD333DDDDDDDDDDDDUUUUUUDDD333UUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDD333UUUDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUfffUUUDDDUUUDDDUUUDDDDDDDDD333DDDDDDUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUDDD333DDDUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDD333UUUDDDDDDUUU333fffUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDUUUDDDDDDDDDDDDDDDDDD333333DDDDDDDDDDDDfffUUUDDDDDDDDD333DDDDDDDDDDDDDDDDDDUUUfffUUUDDDUUUfffUUUUUUUUUDDDDDDDDDUUUDDD333DDDUUUUUUUUUDDD333DDDDDDUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUDDD333DDDUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDD333UUUDDDDDDUUU333fffUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDUUUDDDDDDDDDDDDDDDDDD333333DDDDDDDDDDDDfffUUUDDDDDDDDD333DDDDDDDDDDDDDDDDDDUUUfffUUUDDDUUUfffUUUUUUUUUDDDDDDDDDUUUDDD333DDDUUUUUUUUUDDD333DDDDDDUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUDDD333DDDUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDD333UUUDDDDDDUUU333fffUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUU333UUUDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDDDD333UUUDDDDDDUUU333DDDDDDDDDDDDUUUUUUUUUfffUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUDDDDDD333333333333DDDDDDDDDffffffUUUDDDDDDDDDUUUDDDUUUDDD333UUUUUUUUUUUUUUUffffffUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUU333UUUDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDDDD333UUUDDDDDDUUU333DDDDDDDDDDDDUUUUUUUUUfffUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUDDDDDD333333333333DDDDDDDDDffffffUUUDDDDDDDDDUUUDDDUUUDDD333UUUUUUUUUUUUUUUffffffUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUU333UUUDDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDDDD333UUUDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUfffUUUDDDUUUUUUUUUUUUfffUUUfffUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUfffUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDD333UUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUU333UUUDDD333333333DDDUUUDDDfffDDDDDDDDD333333333333DDDUUUDDDUUUDDDfffDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUDDD333DDDUUUDDDUUUDDDUUUUUUfffUUUDDDUUUUUUUUUUUUfffUUUfffUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUfffUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDD333UUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUU333UUUDDD333333333DDDUUUDDDfffDDDDDDDDD333333333333DDDUUUDDDUUUDDDfffDDDUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUDDD333DDDUUUDDDUUUDDDUUUUUUfffUUUDDDUUUUUUUUUUUUfffUUUfffUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUfffUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDD333UUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUDDDDDDfffUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUDDDfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDD333DDDDDDUUU333DDDDDDDDD333DDDDDDDDDDDDDDDDDD333DDD333333DDDUUUDDDUUUUUUDDDUUUUUU333DDDDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUfffDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDfffUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUfffDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDfffUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUDDDfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDD333DDDDDDUUU333DDDDDDDDD333DDDDDDDDDDDDDDDDDD333DDD333333DDDUUUDDDUUUUUUDDDUUUUUU333DDDDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUfffDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDfffUUUDDDDDDDDDUUUUUUDDDUUUDDDUUUfffDDDDDDUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDfffUUUUUUUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUDDDfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDUUUDDD333DDDDDDUUU333DDDDDDDDD333DDDDDDDDDDDDDDDDDD333DDD333DDDDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDUUU333DDDDDDUUUDDDDDDUUUUUUfffUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDUUUUUU333DDDUUUDDDDDDDDDDDDUUUUUUDDDfffUUUfffDDDUUUUUUUUUDDDUUUDDD333DDDUUUDDDUUUDDDUUUDDDDDDDDDUUU333DDDDDDUUUUUUDDDUUUDDDDDDfffUUUDDDUUUDDD333UUUUUUUUUDDDUUUDDDDDDUUUDDDfffUUUUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDD333DDDDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDUUU333DDDDDDUUUDDDDDDUUUUUUfffUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDUUUUUU333DDDUUUDDDDDDDDDDDDUUUUUUDDDfffUUUfffDDDUUUUUUUUUDDDUUUDDD333DDDUUUDDDUUUDDDUUUDDDDDDDDDUUU333DDDDDDUUUUUUDDDUUUDDDDDDfffUUUDDDUUUDDD333UUUUUUUUUDDDUUUDDDDDDUUUDDDfffUUUUUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDD333DDDDDDUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDUUU333DDDDDDUUUDDDDDDUUUUUUfffUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDUUUUUU333DDDUUUDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUUUU333DDDDDDfff333DDDDDD333UUUUUUDDDUUUUUUUUUUUUfffUUUDDD333DDDDDD333DDDDDD333DDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDD333DDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUfffUUU333DDDDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUUUU333DDDDDDfff333DDDDDD333UUUUUUDDDUUUUUUUUUUUUfffUUUDDD333DDDDDD333DDDDDD333DDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUDDDDDD333DDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUfffUUU333DDDDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUDDDUUUfffUUUDDDDDDUUUUUUUUU333DDDDDDfff333DDDDDD333UUUUUUDDDUUUUUUUUUUUUfffUUUDDD333DDDDDD333DDDDDD333DDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUDDD333UUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDfffDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUfffDDDDDD333UUUUUUDDDDDDUUUUUUDDDDDD333UUUDDDDDDDDDDDDUUUDDDfffDDDDDDUUUUUUDDDUUUDDDUUUDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUDDD333UUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDfffDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUfffDDDDDD333UUUUUUDDDDDDUUUUUUDDDDDD333UUUDDDDDDDDDDDDUUUDDDfffDDDDDDUUUUUUDDDUUUDDDUUUDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUDDD333UUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDfffDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDDDD333UUU333DDDDDDUUUDDDUUUDDDDDDUUU333DDDDDD333DDDDDDDDDUUUUUUDDDUUUDDDUUUfffDDDUUUUUUUUUDDD333DDDDDDDDD333UUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUU333UUUDDDUUUDDDDDDUUUDDDDDDDDD333DDDDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUUUU333DDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDDDD333UUU333DDDDDDUUUDDDUUUDDDDDDUUU333DDDDDD333DDDDDDDDDUUUUUUDDDUUUDDDUUUfffDDDUUUUUUUUUDDD333DDDDDDDDD333UUUUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUU333UUUDDDUUUDDDDDDUUUDDDDDDDDD333DDDDDDDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUUUU333DDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUDDDDDDDDD333UUU333DDDDDDUUUDDDUUUDDDDDDUUU333DDDDDD333DDDDDDDDDUUUUUUDDDUUUDDDUUUfffDDDUUUUUUUUUDDD333DDDDDDDDD333UUUUUUDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDD333UUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDfffDDDDDDDDDUUU333DDD333UUUDDDUUUUUUDDDDDD333DDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUDDD333DDDDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDD333UUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDfffDDDDDDDDDUUU333DDD333UUUDDDUUUUUUDDDDDD333DDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUDDD333DDDDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDD333UUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDfffDDDDDDDDDUUU333DDD333UUUDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUfff333DDDUUUUUUUUUDDDUUUfffUUUUUUUUU333ffffffDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUDDDfff333DDDDDDUUUDDD333DDDDDDUUUDDDUUUDDDDDDUUUDDD333DDD333DDDDDDUUUDDDDDDDDD333DDDDDD333DDD333DDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUfffDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDUUUfffUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUfff333DDDUUUUUUUUUDDDUUUfffUUUUUUUUU333ffffffDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUDDDfff333DDDDDDUUUDDD333DDDDDDUUUDDDUUUDDDDDDUUUDDD333DDD333DDDDDDUUUDDDDDDDDD333DDDDDD333DDD333DDDUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUfffDDDUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDUUUfffUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUUUUfff333DDDUUUUUUUUUDDDUUUfffUUUUUUUUU333ffffffDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUDDDfff333DDDDDDUUUDDD333DDDDDDUUUDDDUUUDDDDDDUUUDDD333DDD333DDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUDDD333UUUUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDfffDDDUUUDDDDDDDDDUUUUUUDDDUUU333DDDUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUDDDDDD333UUUUUUDDDUUUUUUDDDDDDDDDUUUfffDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDDDDUUU333DDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUDDD333UUUUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDfffDDDUUUDDDDDDDDDUUUUUUDDDUUU333DDDUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUDDDDDD333UUUUUUDDDUUUUUUDDDDDDDDDUUUfffDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDDDDDDDUUU333DDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUDDD333UUUUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDfffDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDfffUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDfffUUUUUUUUU333UUUDDDDDDUUUfffUUUDDDUUUfffUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDfffUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDfffUUUUUUUUU333UUUDDDDDDUUUfffUUUDDDUUUfffUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDfffUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUfffDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUfffDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUU333DDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUfffUUUUUUUUUUUUDDD333UUUDDDUUUDDDfffDDDDDDUUUfffDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUfffDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUU333DDDUUUDDDUUUUUUDDDUUUDDDDDDDDDDDD333DDDDDDDDDUUUDDDUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUfffUUUUUUUUUUUUDDD333UUUDDDUUUDDDfffDDDDDDUUUfffDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDUUU333DDDDDDDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUfffDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUU333DDDUUUDDDUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUU333DDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUfffDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDDUUUDDD333DDDUUUUUUUUUDDD333DDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUffffffUUUDDDUUUDDDfffDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUU333DDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUfffDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDDUUUDDD333DDDUUUUUUUUUDDD333DDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUffffffUUUDDDUUUDDDfffDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUU333DDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUfffDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUUUUDDD333UUUUUUDDDDDDDDDUUUDDD333DDDUUUUUUUUUDDD333DDDDDDDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDfffUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUfffDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDD333DDDUUUUUUDDDDDD333333DDDDDDDDDUUUUUUUUU333DDD333DDDDDDDDDDDD333DDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUDDDUUU333DDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUfffUUUUUUffffffDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDD333DDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDfffUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUfffDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDD333DDDUUUUUUDDDDDD333333DDDDDDDDDUUUUUUUUU333DDD333DDDDDDDDDDDD333DDDUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUDDDUUU333DDDUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUfffUUUUUUffffffDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDD333DDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUUUUDDDUUUDDDDDDDDDfffUUUDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUfffDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDD333DDDUUUUUUDDDDDD333333DDDDDDDDDUUUUUUUUU333DDDUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDD333DDDDDD333UUUDDDUUUUUUDDD333DDDDDDUUUDDD333UUUDDDDDD333DDDDDDDDDDDDDDDDDDDDDUUUDDDfffDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUffffffUUUDDDUUUUUUUUUDDDUUUffffffffffffUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDDDDD333DDDUUUDDDDDDUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDD333DDDDDD333UUUDDDUUUUUUDDD333DDDDDDUUUDDD333UUUDDDDDD333DDDDDDDDDDDDDDDDDDDDDUUUDDDfffDDDDDDUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUffffffUUUDDDUUUUUUUUUDDDUUUffffffffffffUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDDDDD333DDDUUUDDDDDDUUUDDDUUUfffDDDUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDDDD333DDDDDD333UUUDDDUUUUUUDDD333DDDDDDUUUDDD333UUUDDDDDD333DDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUU333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDfffDDDfffUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDDDD333UUUDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDDUUUUUUfffUUUUUUDDDfffUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUU333DDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUU333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDfffDDDfffUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDDDD333UUUDDDUUUDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUDDDUUUUUUfffUUUUUUDDDfffUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUUUU333DDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUU333DDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDDDDfffDDDfffUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDD333DDDUUUUUUDDDDDDDDDUUUDDD333DDDDDDDDDUUUDDDUUU333333333DDDUUUfffUUUUUUUUUUUUDDDDDDDDD333333DDDDDD333DDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUfffDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDD333333UUUDDDUUUDDDUUUUUUUUU333DDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUfffDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDD333DDDUUUUUUDDDDDDDDDUUUDDD333DDDDDDDDDUUUDDDUUU333333333DDDUUUfffUUUUUUUUUUUUDDDDDDDDD333333DDDDDD333DDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUfffDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDDDD333333UUUDDDUUUDDDUUUUUUUUU333DDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUfffDDDDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDD333DDDUUUUUUDDDDDDDDDUUUDDD333DDDDDDDDDUUUDDDUUU333333333DDDUUUfffUUUUUUUUUUUUDDDDDDDDD333333DDDDDD333DDDUUUDDDUUUDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUU333UUU333DDDDDDDDDUUUUUUDDDDDDUUUUUUDDD333UUU333DDDDDDUUUDDDfffUUU333DDDDDDDDDUUUUUUUUUUUUDDDDDDUUU333DDDDDDDDDDDDDDDDDD333UUUfffUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUDDD333UUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDD333DDDDDDDDDfffDDDDDDDDDDDDDDDDDDUUUffffffUUUUUUDDDUUUfffUUUUUUDDDDDDUUUUUUUUUffffffDDDDDDUUUDDDUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUU333UUU333DDDDDDDDDUUUUUUDDDDDDUUUUUUDDD333UUU333DDDDDDUUUDDDfffUUU333DDDDDDDDDUUUUUUUUUUUUDDDDDDUUU333DDDDDDDDDDDDDDDDDD333UUUfffUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUDDD333UUUUUUUUUDDDUUUDDDDDDUUUUUUUUUUUUDDDDDD333DDDDDDDDDfffDDDDDDDDDDDDDDDDDDUUUffffffUUUUUUDDDUUUfffUUUUUUDDDDDDUUUUUUUUUffffffDDDDDDUUUDDDUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUU333UUU333DDDDDDDDDUUUUUUDDDDDDUUUUUUDDD333UUU333DDDDDDUUUDDDfffUUU333DDDDDDDDDUUUUUUUUUUUUDDDDDDUUU333DDDDDDDDDDDDDDDDDD333UUUfffUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUU333DDDDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDDDDUUUDDD333UUUUUUUUUUUUDDDUUUDDDDDDDDD333DDD333DDDDDDDDDfffDDDUUUDDDUUUUUUfffUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUDDDUUU333DDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUfffUUUUUUDDDUUUDDDDDDDDDUUUUUUDDDUUU333DDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUU333DDDDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDDDDUUUDDD333UUUUUUUUUUUUDDDUUUDDDDDDDDD333DDD333DDDDDDDDDfffDDDUUUDDDUUUUUUfffUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUDDDUUU333DDDDDDDDDDDDUUUDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUUUUfffUUUUUUDDDUUUDDDDDDDDDUUUUUUDDDUUU333DDDDDDDDDDDDUUUDDDUUUDDDDDDDDDDDDUUU333DDDDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDDDDUUUDDD333UUUUUUUUUUUUDDDUUUDDDDDDDDD333DDD333DDDDDDDDDfffDDDUUUDDDUUUUUUfffUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUU333333333DDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDD333333DDDDDD333DDD333333DDDDDDDDDUUUDDDDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDDDD333DDD333DDDUUUDDDUUUDDDUUUDDDUUUUUUDDDDDD333DDDUUUUUUDDDDDD333UUUUUUUUUDDD333UUUUUUDDDDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUfffDDDDDDDDD333UUUDDDDDDDDDDDDUUU333DDDDDD333DDD333UUUDDDDDDDDD333333333DDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDD333333DDDDDD333DDD333333DDDDDDDDDUUUDDDDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDDDD333DDD333DDDUUUDDDUUUDDDUUUDDDUUUUUUDDDDDD333DDDUUUUUUDDDDDD333UUUUUUUUUDDD333UUUUUUDDDDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUfffDDDDDDDDD333UUUDDDDDDDDDDDDUUU333DDDDDD333DDD333UUUDDDDDDDDD333333333DDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDD333333DDDDDD333DDD333333DDDDDDDDDUUUDDDDDDDDD333DDDUUUUUUUUUDDDDDDDDDDDDDDD333DDD333DDDUUUDDDUUUDDDUUUDDDUUUUUUDDDDDD333DDDUUUUUUDDDDDD333UUUUUUUUUDDD333333DDDDDDUUUUUUUUUDDDDDDDDDDDD333UUUUUUDDDDDDDDDDDDDDDUUUDDD333UUUDDDDDDUUUUUUUUUDDD333DDDDDDDDDUUUDDDDDDDDDDDD333333DDD333333UUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDD333DDD333DDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUU333333UUUUUUDDDDDDDDDfffDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUDDD333333DDD333333DDDUUUDDDDDDUUUDDD333DDDDDDUUUUUUUUUDDDDDDDDDDDD333UUUUUUDDDDDDDDDDDDDDDUUUDDD333UUUDDDDDDUUUUUUUUUDDD333DDDDDDDDDUUUDDDDDDDDDDDD333333DDD333333UUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDD333DDD333DDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDDDDDDD333DDDUUU333333UUUUUUDDDDDDDDDfffDDDDDDDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUDDD333333DDD333333DDDUUUDDDDDDUUUDDD333DDDDDDUUUUUUUUUDDDDDDDDDDDD333UUUUUUDDDDDDDDDDDDDDDUUUDDD333UUUDDDDDDUUUUUUUUUDDD333DDDDDDDDDUUUDDDDDDDDDDDD333333DDD333333UUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDDDDDDD333DDD333DDDUUUUUUDDDDDDDDD333UUUDDDUUUDDDDDDDDD333DDDDDDUUUDDDUUU333UUUUUUUUUUUUDDD333DDD333DDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDD333DDD333333DDDDDD333UUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUDDDUUUUUUDDDUUUUUUUUUfffDDDDDDUUUDDDDDDDDDDDDUUU333DDDUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUDDD333DDDUUUUUUDDDDDDffffffDDDUUUUUUDDDUUUDDDUUUDDDUUUUUUDDDDDDUUUfffUUUUUUUUUUUUUUUDDDDDD333333DDD333333333333333333DDD333DDDDDDDDD333UUUDDDUUUDDDDDDDDD333DDDDDDUUUDDDUUU333UUUUUUUUUUUUDDD333DDD333DDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDD333DDD333333DDDDDD333UUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUDDDUUUUUUDDDUUUUUUUUUfffDDDDDDUUUDDDDDDDDDDDDUUU333DDDUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUDDD333DDDUUUUUUDDDDDDffffffDDDUUUUUUDDDUUUDDDUUUDDDUUUUUUDDDDDDUUUfffUUUUUUUUUUUUUUUDDDDDD333333DDD333333333333333333DDD333DDDDDDDDD333UUUDDDUUUDDDDDDDDD333DDDDDDUUUDDDUUU333UUUUUUUUUUUUDDD333DDD333DDDDDDUUUUUUUUUDDDDDDDDDUUUDDDDDD333DDD333333DDDDDD333UUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUDDDUUUUUUDDDUUUUUUUUUfffDDDDDDUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDD333333UUUDDDUUUDDDUUUDDDDDDDDD333DDD333DDDUUU333DDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUUUUUUU333DDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUfffUUUUUUfffUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDDDD333333DDDDDD333333333DDDDDD333333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDD333333UUUDDDUUUDDDUUUDDDDDDDDD333DDD333DDDUUU333DDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUUUUUUU333DDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUfffUUUUUUfffUUUUUUUUUUUUUUUUUUDDDDDDDDD333DDDDDD333333DDDDDD333333333DDDDDD333333DDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDD333333UUUDDDUUUDDDUUUDDDDDDDDD333DDD333DDDUUU333DDDDDDUUUDDDUUUUUUDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDD333DDD333DDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDD333UUUDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333DDDDDDDDDUUUUUUDDDUUUUUUUUUDDDUUU333DDDUUUUUUDDDDDD333UUUDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUUUU333DDD333333UUUDDD333UUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDD333DDD333DDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDD333UUUDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333DDDDDDDDDUUUUUUDDDUUUUUUUUUDDDUUU333DDDUUUUUUDDDDDD333UUUDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUUUU333DDD333333UUUDDD333UUUDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDD333DDD333DDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUDDDDDDDDDDDDUUUDDD333UUUDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDfffDDDUUUUUUUUUUUUUUU333DDDUUUDDDDDDDDDDDDDDDUUUDDDUUU333DDDDDDDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDfffUUUUUUUUUUUUDDD333DDDDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDUUUfffUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUUUUDDDUUUUUUfffUUUUUUUUUDDDDDDUUU333DDDDDDUUUDDDDDD333DDDUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDfffDDDUUUUUUUUUUUUUUU333DDDUUUDDDDDDDDDDDDDDDUUUDDDUUU333DDDDDDDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDfffUUUUUUUUUUUUDDD333DDDDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDUUUfffUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUUUUDDDUUUUUUfffUUUUUUUUUDDDDDDUUU333DDDDDDUUUDDDDDD333DDDUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDfffDDDUUUUUUUUUUUUUUU333DDDUUUDDDDDDDDDDDDDDDUUUDDDUUU333DDDDDDDDD333DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUDDDfffUUUUUUUUUUUUDDD333DDDDDDDDDDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDfffUUUUUUUUUDDDUUUUUUUUUDDD333DDDDDDUUUUUUDDD333DDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDD333fffUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUU333333DDDDDD333DDDDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUfffUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDfffUUUUUUUUUDDDUUUUUUUUUDDD333DDDDDDUUUUUUDDD333DDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDD333fffUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUU333333DDDDDD333DDDDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUfffUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDDDDDDDfffUUUUUUUUUDDDUUUUUUUUUDDD333DDDDDDUUUUUUDDD333DDDUUUUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDDDD333fffUUUUUUUUUUUUDDDUUUUUUDDDUUUUUUUUU333333DDDDDD333DDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333DDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDD333DDDDDDDDD333DDDDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUUUUDDDDDDDDD333333DDDUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUffffffDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUDDD333DDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333DDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDD333DDDDDDDDD333DDDDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUUUUDDDDDDDDD333333DDDUUUDDDUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUffffffDDDUUUUUUUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDUUUDDD333DDDDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUDDD333DDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDUUUUUUDDDDDDUUUDDDDDDDDD333DDDDDDDDD333DDDDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDfffUUUUUUDDDDDDDDD333333DDDUUUDDDUUUUUUDDDDDDUUUUUUDDDUUUUUUfffUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUU333DDDDDDUUUDDDUUUDDDDDDUUU333333DDD333DDDDDDDDDDDDDDDDDDUUU333DDDUUUDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUfffDDDUUUUUUDDDUUUDDDUUU333DDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUU333UUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUU333DDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUfffUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUU333DDDDDDUUUDDDUUUDDDDDDUUU333333DDD333DDDDDDDDDDDDDDDDDDUUU333DDDUUUDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUfffDDDUUUUUUDDDUUUDDDUUU333DDDDDDDDDDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUDDDUUUUUUDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUUUUUUU333UUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUU333DDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUfffUUUUUUUUUUUUDDDDDDDDDUUUDDDDDDUUU333DDDDDDUUUDDDUUUDDDDDDUUU333333DDD333DDDDDDDDDDDDDDDDDDUUU333DDDUUUDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDDDDDDD333DDD333DDDUUUUUUUUUUUUfffDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDD333333DDDDDD333DDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUDDD333DDDDDDUUUUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUU333UUUDDDUUUUUUDDD333UUUfffDDDUUUDDDDDDDDD333UUUDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDD333DDD333UUUUUUDDDUUUDDDUUU333DDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDD333333DDDDDD333DDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUDDD333DDDDDDUUUUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUDDDUUU333UUUDDDUUUUUUDDD333UUUfffDDDUUUDDDDDDDDD333UUUDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDDDDDDD333DDD333UUUUUUDDDUUUDDDUUU333DDDDDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUDDDDDDDDDDDD333333DDDDDD333DDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUDDD333DDDDDDUUUUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDfffUUUUUUDDD333DDDDDDDDDUUUUUUDDD333UUUDDDDDDDDDUUUDDDDDDUUUUUUUUUDDDUUU333DDDUUUDDDDDDUUUffffffDDDUUUDDDDDD333UUUDDDUUUDDDUUUDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDD333DDDUUUUUU333DDDDDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDUUUDDDfff333DDDDDDUUUfffUUU333333333DDDDDDDDDDDDDDDDDDDDDfffDDDDDDDDDDDDUUUUUUDDD333UUU333UUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUDDDfffUUUUUUDDD333DDDDDDDDDUUUUUUDDD333UUUDDDDDDDDDUUUDDDDDDUUUUUUUUUDDDUUU333DDDUUUDDDDDDUUUffffffDDDUUUDDDDDD333UUUDDDUUUDDDUUUDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDUUUDDDDDD333DDDUUUUUU333DDDDDDDDDUUUDDDDDD333DDDUUUDDDDDDDDDUUUDDDfff333DDDDDDUUUfffUUU333333333DDDDDDDDDDDDDDDDDDDDDfffDDDDDDDDDDDDUUUUUUDDD333UUU333UUUDDDUUUUUUDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUDDDfffUUUUUUDDD333DDDDDDDDDUUUUUUDDD333UUUDDDDDDDDDUUUDDDDDDUUUUUUUUUDDDUUU333DDDUUUDDDDDDUUUffffffDDDUUUDDDDDD333UUUDDDUUUDDDUUUDDD333DDDDDDDDDUUUUUUUUUDDDDDDDDDUUUDDDUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDD333DDDUUUUUUDDDUUUDDD333333DDD333333DDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUU333DDDDDDUUUUUUUUUUUUUUU333DDDDDDUUUDDDDDDDDDDDD333DDDDDDUUUUUUUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDUUU333DDDUUUUUUDDD333DDDDDDUUUDDD333333DDDDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDDDDffffffDDD333DDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDD333DDDDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDD333DDDUUUUUUDDDUUUDDD333333DDD333333DDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUU333DDDDDDUUUUUUUUUUUUUUU333DDDDDDUUUDDDDDDDDDDDD333DDDDDDUUUUUUUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDUUU333DDDUUUUUUDDD333DDDDDDUUUDDD333333DDDDDDUUUUUUUUUUUUDDDUUUUUUDDDDDDDDD333DDDDDDDDDDDDDDDffffffDDD333DDDDDDUUUUUUUUUDDDDDDDDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDD333DDDDDDDDDUUUUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDDDDDDD333DDDUUUUUUDDDUUUDDD333333DDD333333DDDDDDDDDDDDDDDUUUUUUDDDUUUDDDUUU333DDDDDDUUUUUUUUUUUUUUU333DDDDDDUUUDDDDDDDDDDDD333DDDDDDUUUUUUUUUfffUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUUUUfffUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDDDD333DDDUUUDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDUUU333DDDUUUUUUUUUDDDUUUUUUUUUfffUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUDDDUUU333DDD333DDDDDDUUUDDDUUUDDDDDDDDDUUUUUUfffUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDDDD333DDDUUUDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUDDDDDDUUU333DDDUUUUUUUUUDDDUUUUUUUUUfffUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUUUUUUUDDDUUU333DDD333DDDDDDUUUDDDUUUDDDDDDDDDUUUUUUfffUUUUUUDDDDDDDDD333DDDDDDUUUDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDDDDUUUUUUUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUUUUDDDUUUDDDDDDUUUfffUUUfffUUUUUUDDDDDDDDD333UUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUfffUUU333UUUfffUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUfffUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDfffUUUDDDUUUUUUUUUfffUUUUUUDDDUUUDDDDDDfffDDDDDDDDDUUUDDDfffDDDUUUDDDUUUDDDDDD333UUUDDDUUUDDDDDDDDDDDDUUUfffUUUfffUUUUUUDDDDDDDDD333UUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUfffUUU333UUUfffUUUDDDUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUfffUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDfffUUUDDDUUUUUUUUUfffUUUUUUDDDUUUDDDDDDfffDDDDDDDDDUUUDDDfffDDDUUUDDDUUUDDDDDD333UUUDDDUUUDDDDDDDDDDDDUUUfffUUUfffUUUUUUDDDDDDDDD333UUUDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUfffUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDUUUUUUfffUUU333fffUUUUUUUUUDDDDDDDDDUUU333DDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDfffDDDDDDfffDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDUUUUUUUUU333DDDDDDDDDDDDDDDDDDUUUDDDDDD333DDDDDDUUUDDDDDDDDDUUUUUUUUUUUUffffffUUUDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUfffUUUfffUUUDDDUUUDDDUUUUUUDDDUUU333DDDUUUfffUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDfffUUUUUUUUUDDDDDDDDDUUU333DDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDfffDDDDDDfffDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDUUUUUUUUU333DDDDDDDDDDDDDDDDDDUUUDDDDDD333DDDDDDUUUDDDDDDDDDUUUUUUUUUUUUffffffUUUDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUfffUUUfffUUUDDDUUUDDDUUUUUUDDDUUU333DDDUUUfffUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUUUUDDDDDDDDDfffUUUUUUUUUDDDDDDDDDUUU333DDDDDDDDDDDDDDDDDDDDDDDDUUUDDDDDDDDDUUUDDDDDDDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDfffDDDDDDfffDDDDDDUUUUUUDDDDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUDDDDDDUUUUUUUUUDDDUUUUUUUUU333DDDDDDUUUfffDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUUUU333UUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffUUUUUUDDDDDDUUUfffDDDUUU333UUUDDD333UUU333UUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDfffUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUfffffffffDDDDDDUUUDDDfffDDDfffUUUUUUUUUUUUUUUUUUUUUDDDUUUfffUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDfffDDDDDDUUU333DDDDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUfffDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUUUU333UUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffUUUUUUDDDDDDUUUfffDDDUUU333UUUDDD333UUU333UUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDfffUUUUUUDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDDDDUUUUUUfffffffffDDDDDDUUUDDDfffDDDfffUUUUUUUUUUUUUUUUUUUUUDDDUUUfffUUUUUUUUUDDDUUUDDDUUUUUUDDDDDDDDDfffDDDDDDUUU333DDDDDDDDDDDDUUUUUUUUUUUUDDDDDDUUUUUUfffDDDDDDDDDDDDUUUDDDDDDDDDDDDDDDUUUDDDDDDUUUUUU333UUUDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDUUUfffUUUUUUDDDDDDUUUfffDDDUUU333UUUDDD333UUU333UUUUUUUUUUUUDDDDDDUUUUUUUUUDDDDDDUUUUUUDDDDDDDDDUUUUUUDDDUUUUUUUUUUUU333DDDDDDDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDD333fffDDDDDDDDDDDD333DDDUUUUUUUUUUUUUUUDDDDDD333UUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUUUUUUUDDDUUUffffff333UUUUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDDDDDDD333UUUUUUfffDDDUUUUUUDDDUUUUUUDDDUUUDDDfffUUUUUUUUU333DDDDDDDDDUUUUUUUUUDDDfffDDDUUUfffDDDUUUDDDDDDDDDUUUUUUUUUDDDDDD333DDDUUUUUUUUUDDDUUUUUUUUUUUU333DDDDDDDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDD333fffDDDDDDDDDDDD333DDDUUUUUUUUUUUUUUUDDDDDD333UUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUUUUUUUDDDUUUffffff333UUUUUUUUUUUUUUUDDDUUUDDDUUUDDDDDDDDDDDDDDD333UUUUUUfffDDDUUUUUUDDDUUUUUUDDDUUUDDDfffUUUUUUUUU333DDDDDDDDDUUUUUUUUUDDDfffDDDUUUfffDDDUUUDDDDDDDDDUUUUUUUUUDDDDDD333DDDUUUUUUUUUDDDUUUUUUUUUUUU333DDDDDDDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDUUUDDDDDDDDDDDD333fffDDDDDDDDDDDD333DDDUUUUUUUUUUUUUUUDDDDDD333UUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUfffDDDDDDUUUfffDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDDDD333DDDDDDUUU333DDDDDDDDDUUUUUUUUUDDDUUUDDD333DDDDDDDDDfffUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUfffDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDfffDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDDDD333DDDffffffDDDDDDUUUfffDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDDDD333DDDDDDUUU333DDDDDDDDDUUUUUUUUUDDDUUUDDD333DDDDDDDDDfffUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffUUUUUUDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUDDDDDDDDDUUUUUUfffDDDDDDUUUUUUDDDDDDUUUUUUUUUDDDfffDDDDDDDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDDDDDDDUUUDDDUUUUUUDDDDDD333DDDffffffDDDDDDUUUfffDDDDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDUUUUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUUUUDDDUUUDDDDDDDDD333DDDDDDUUU333DDDDDDDDDUUUUUUUUUDDDUUUDDD333DDDDDDDDDfffUUUDDDDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUU333DDDUUUDDDDDDUUUUUUfffDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDUUUfffDDDDDDDDDUUUDDDDDDDDDDDDfffUUU333DDDDDDDDDfffUUU333DDDUUUfffDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUfffUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUUUU333DDDUUUDDDDDDUUUUUUfffDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDUUUfffDDDDDDDDDUUUDDDDDDDDDDDDfffUUU333DDDDDDDDDfffUUU333DDDUUUfffDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUDDDUUUUUUDDDDDDDDDDDDDDD333DDDDDDDDDDDDDDDUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUfffUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUfffDDDUUUDDDDDDDDDDDDUUUUUUDDDUUUUUUUUU333DDDUUUDDDDDDUUUUUUfffDDDDDDUUUUUUUUUDDDDDD333UUUDDDDDDDDDUUUUUUUUUDDDUUUfffDDDDDDDDDUUUDDDDDDDDDDDDfffUUU333DDDDDDDDDfffUUU333DDDUUUfffDDDUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUfffUUUDDDUUUUUUUUUUUU333DDDDDDUUUDDDUUUUUUfffUUUDDDUUUDDDUUUUUUDDDDDD333DDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDffffffDDDDDDUUUUUUDDDDDDDDDDDD333333333UUUDDD333DDDUUUDDDUUUUUUDDDUUUUUUUUUffffffUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUfffDDDUUUDDDDDDUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUUUUUUU333DDDDDDUUUDDDUUUUUUfffUUUDDDUUUDDDUUUUUUDDDDDD333DDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDffffffDDDDDDUUUUUUDDDDDDDDDDDD333333333UUUDDD333DDDUUUDDDUUUUUUDDDUUUUUUUUUffffffUUUDDDDDDUUUUUUUUUUUUDDDDDDUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDUUUDDDUUUUUUUUUfffDDDUUUDDDDDDUUUUUUUUUDDDUUUDDDDDDDDDDDDUUUfffUUUUUUUUUUUU333DDDDDDUUUDDDUUUUUUfffUUUDDDUUUDDDUUUUUUDDDDDD333DDDDDDDDDUUUDDDUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUUUUUUUUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDffffffDDDDDDDDDDDDDDD333DDDUUUDDDDDDUUU333DDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDfffUUUffffffUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUUUUfffUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDfffUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDDDD333UUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDUUU333DDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDfffUUUffffffUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDDDDDDDUUUDDDUUUDDDUUUUUUfffUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDfffUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDDDD333UUUUUUDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDDDDDDD333DDDUUUDDDDDDUUU333DDDDDDDDDDDDDDDUUUDDDDDDUUUDDDUUUUUUDDDfffUUUffffffUUUDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDUUUDDDDDDUUUUUUUUUUUUfffDDDUUUDDDUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUU333UUUDDD333DDDUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDffffffUUUUUUUUUUUUDDDDDDUUUfffUUUUUUUUUfffUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUDDDUUUDDDDDD333DDDUUUUUUUUUDDDUUUUUUUUUfffDDDUUUDDD333UUUUUUUUUfffUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDfffUUUUUU333UUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUU333UUUDDD333DDDUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDffffffUUUUUUUUUUUUDDDDDDUUUfffUUUUUUUUUfffUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDUUUDDDDDDDDDUUUUUUDDDUUUDDDDDD333DDDUUUUUUUUUDDDUUUUUUUUUfffDDDUUUDDD333UUUUUUUUUfffUUUUUUUUUUUUUUUffffffUUUUUUUUUDDDDDDUUUDDDDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDfffUUUUUU333UUUUUUUUUDDDUUUDDDUUUUUUDDDDDDUUUDDDDDDDDDDDDDDDDDDDDDDDDUUU333UUUDDD333DDDUUUUUUDDDDDDUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDUUUDDDDDDffffffUUUUUUUUUUUUDDDDDDUUUfffUUUUUUUUUfffUUUUUUUUUUUUUUUUUUUUUUUUUUUDDDDDDDDDDDD333DDDDDDUUUUUUDDDDDDUUUfffUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDffffffUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUfffUUUDDDUUUUUUUUUDDDUUUfffDDDUUUfffUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDUUU333333DDDDDDDDDDDDfffUUUUUUUUUUUUffffffDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDD333DDDDDDUUUUUUDDDDDDUUUfffUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDffffffUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUfffUUUDDDUUUUUUUUUDDDUUUfffDDDUUUfffUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDDDDUUUUUUDDDUUU333333DDDDDDDDDDDDfffUUUUUUUUUUUUffffffDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDUUUDDDUUUDDDUUUUUUDDDUUUUUUUUUDDDDDDDDDDDDDDD333DDDDDDUUUUUUDDDDDDUUUfffUUUUUUDDDDDDUUUUUUUUUDDDUUUUUUUUUUUUUUUUUUDDDUUUDDDffffffUUUDDDDDDDDDUUUUUUDDDDDDUUUUUUfffUUUDDDUUUUUUUUUDDDUUUfffDDDUUUfffUUUUUUUUUDDDUUUDDDUUUDDDDDDUUUDDDDDDUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUffffffUUUUUUDDDUUUUUUUUUUUUfffUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDDDD333DDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUfffUUUfffffffffDDDUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDfffDDDUUUUUUDDDUUUUUUDDDUUUUUUDDDDDDDDDDDD333333UUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUffffffUUUUUUDDDUUUUUUUUUUUUfffUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDDDD333DDDDDDUUUDDDUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUUUUfffUUUfffffffffDDDUUUUUUfffDDDUUUUUUUUUUUUUUUUUUUUUDDDUUUUUUUUUDDDUUUDDDfffDDDUUUUUUDDDUUUUUUDDDUUUUUUDDDDDDDDDDDD333333UUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUDDDUUUDDDUUUUUUDDDUUUDDDDDDUUUDDDUUUUUUUUUDDDDDDDDDDDDUUUDDDDDDUUUUUUffffffUUUUUUDDDUUUUUUUUUUUUfffUUUDDDDDDUUUUUUUUUUUUUUUDDDUUUUUUDDDDDDUUUUUUDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUU333DDDfffUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUUUUDDDfffDDDUUUUUUUUUUUUUUUUUUfffDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDDDD333UUUUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUfffUUUfffDDDUUUDDDUUUUUUUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUU333DDDfffUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUUUUDDDfffDDDUUUUUUUUUUUUUUUUUUfffDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUUUUUDDDDDDDDDDDD333UUUUUUDDDUUUDDDUUUUUUUUUDDDDDDUUUUUUUUUUUUfffUUUUUUUUUDDDUUUfffUUUUUUUUUUUUUUUDDDDDDUUUUUUDDDUUUUUUDDDDDDUUUUUUUUUUUUUUUfffUUUfffDDDUUUDDDUUUUUUUUUDDD333DDDUUUDDDDDDDDDDDDDDDDDDDDDUUUUUUDDDDDDUUUDDDUUUDDDDDDDDDDDDDDDDDDUUU333DDDfffUUUDDDDDDUUUUUUDDDUUUDDDUUUUUUUUUDDDUUUDDDUUUUUUfffDDDUUUUUUUUUUUUDDDfffDDDUUUUUUUUUUUUUUUUUUfffDDDUUUDDDDDDDDDDDDDDDDDDUUUUUUUUUDDDUUU \ No newline at end of file diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc new file mode 100644 index 0000000000..021da1626b --- /dev/null +++ b/gtk2_ardour/streamview.cc @@ -0,0 +1,921 @@ +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "streamview.h" +#include "regionview.h" +#include "audio_time_axis.h" +#include "canvas-waveview.h" +#include "canvas-simplerect.h" +#include "region_selection.h" +#include "selection.h" +#include "public_editor.h" +#include "ardour_ui.h" +#include "crossfade_view.h" +#include "rgb_macros.h" +#include "extra_bind.h" +#include "gui_thread.h" + +using namespace ARDOUR; +using namespace Editing; + +StreamView::StreamView (AudioTimeAxisView& tv) + : _trackview (tv) +{ + region_color = _trackview.color(); + crossfades_visible = true; + + if (tv.is_audio_track()) { + /* TRACK */ + //stream_base_color = RGBA_TO_UINT (222,223,218,255); + stream_base_color = color_map[cAudioTrackBase]; + } else { + /* BUS */ + //stream_base_color = RGBA_TO_UINT (230,226,238,255); + stream_base_color = color_map[cAudioBusBase]; + } + + /* set_position() will position the group */ + + canvas_group = gtk_canvas_item_new (GTK_CANVAS_GROUP(_trackview.canvas_display), + gtk_canvas_group_get_type (), + NULL); + + canvas_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_group), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 1000000.0, + "y2", (double) tv.height, + "outline_color_rgba", color_map[cAudioTrackOutline], + /* outline ends and bottom */ + "outline_what", (guint32) (0x1|0x2|0x8), + "fill_color_rgba", stream_base_color, + NULL); + + gtk_signal_connect (GTK_OBJECT(canvas_rect), "event", + (GtkSignalFunc) PublicEditor::canvas_stream_view_event, &_trackview); + + _samples_per_unit = _trackview.editor.get_current_zoom(); + _amplitude_above_axis = 1.0; + + if (_trackview.is_audio_track()) { + _trackview.audio_track()->diskstream_changed.connect (slot (*this, &StreamView::diskstream_changed)); + _trackview.session().TransportStateChange.connect (slot (*this, &StreamView::transport_changed)); + _trackview.get_diskstream()->record_enable_changed.connect (slot (*this, &StreamView::rec_enable_changed)); + _trackview.session().RecordEnabled.connect (slot (*this, &StreamView::sess_rec_enable_changed)); + _trackview.session().RecordDisabled.connect (slot (*this, &StreamView::sess_rec_enable_changed)); + } + + rec_updating = false; + rec_active = false; + use_rec_regions = tv.editor.show_waveforms_recording (); + last_rec_peak_frame = 0; +} + +StreamView::~StreamView () +{ + undisplay_diskstream (); + gtk_object_destroy (GTK_OBJECT(canvas_group)); +} + +void +StreamView::attach () +{ + if (_trackview.is_audio_track()) { + display_diskstream (_trackview.get_diskstream()); + } +} + +int +StreamView::set_position (gdouble x, gdouble y) + +{ + gtk_canvas_item_set (canvas_group, "x", x, "y", y, NULL); + return 0; +} + +int +StreamView::set_height (gdouble h) +{ + /* limit the values to something sane-ish */ + + if (h < 10.0 || h > 1000.0) { + return -1; + } + + gtk_object_set (GTK_OBJECT(canvas_rect), "y2", h, NULL); + + for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { + (*i)->set_height (h); + } + + for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + (*i)->set_height (h); + } + + for (vector::iterator i = rec_rects.begin(); i != rec_rects.end(); ++i) { + RecBoxInfo &recbox = (*i); + gtk_object_set (GTK_OBJECT( recbox.rectangle ), "y2", h - 1, NULL); + } + + return 0; +} + +int +StreamView::set_samples_per_unit (gdouble spp) +{ + AudioRegionViewList::iterator i; + + if (spp < 1.0) { + return -1; + } + + _samples_per_unit = spp; + + for (i = region_views.begin(); i != region_views.end(); ++i) { + (*i)->set_samples_per_unit (spp); + } + + for (CrossfadeViewList::iterator xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) { + (*xi)->set_samples_per_unit (spp); + } + + for (vector::iterator xi = rec_rects.begin(); xi != rec_rects.end(); ++xi) { + RecBoxInfo &recbox = (*xi); + + gdouble xstart = _trackview.editor.frame_to_pixel ( recbox.start ); + gdouble xend = _trackview.editor.frame_to_pixel ( recbox.start + recbox.length ); + + gtk_canvas_item_set (recbox.rectangle, "x1", xstart, NULL); + gtk_canvas_item_set (recbox.rectangle, "x2", xend, NULL); + } + + return 0; +} + +int +StreamView::set_amplitude_above_axis (gdouble app) + +{ + AudioRegionViewList::iterator i; + + if (app < 1.0) { + return -1; + } + + _amplitude_above_axis = app; + + for (i = region_views.begin(); i != region_views.end(); ++i) { + (*i)->set_amplitude_above_axis (app); + } + + return 0; +} + +void +StreamView::add_region_view (Region *r) +{ + add_region_view_internal (r, true); +} + +void +StreamView::add_region_view_internal (Region *r, bool wait_for_waves) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &StreamView::add_region_view), r)); + + AudioRegion* region = dynamic_cast (r); + + if (region == 0) { + return; + } + + AudioRegionView *region_view; + list::iterator i; + + for (i = region_views.begin(); i != region_views.end(); ++i) { + if (&(*i)->region == region) { + + /* great. we already have a AudioRegionView for this Region. use it again. + */ + + (*i)->set_valid (true); + return; + } + } + + region_view = new AudioRegionView (GTK_CANVAS_GROUP(canvas_group), + _trackview, + *region, + _samples_per_unit, + _amplitude_above_axis, + region_color, + wait_for_waves); + + region_views.push_front (region_view); + + /* follow global waveform setting */ + + region_view->set_waveform_visible(_trackview.editor.show_waveforms()); + + /* catch regionview going away */ + + region->GoingAway.connect (slot (*this, &StreamView::remove_region_view)); + + AudioRegionViewAdded (region_view); +} + +void +StreamView::remove_region_view (Region *r) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &StreamView::remove_region_view), r)); + + AudioRegion* ar = dynamic_cast (r); + + if (ar == 0) { + return; + } + + for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { + if (&((*i)->region) == ar) { + delete *i; + region_views.erase (i); + break; + } + } + + for (list::iterator i = crossfade_views.begin(); i != crossfade_views.end();) { + list::iterator tmp; + + tmp = i; + ++tmp; + + if ((*i)->crossfade.involves (*ar)) { + delete *i; + crossfade_views.erase (i); + } + + i = tmp; + } +} + +void +StreamView::remove_rec_region (Region *r) +{ + ENSURE_GUI_THREAD(bind (slot (*this, &StreamView::remove_rec_region), r)); + + if (!Gtkmmext::UI::instance()->caller_is_gui_thread()) { + fatal << "region deleted from non-GUI thread!" << endmsg; + /*NOTREACHED*/ + } + + AudioRegion* ar = dynamic_cast (r); + + if (ar == 0) { + return; + } + + for (list::iterator i = rec_regions.begin(); i != rec_regions.end(); ++i) { + if (*i == ar) { + rec_regions.erase (i); + break; + } + } +} + +void +StreamView::undisplay_diskstream () +{ + for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { + delete *i; + } + + for (CrossfadeViewList::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + delete *i; + } + + region_views.clear(); + crossfade_views.clear (); +} + +void +StreamView::display_diskstream (DiskStream *ds) +{ + playlist_change_connection.disconnect(); + playlist_changed (ds); + playlist_change_connection = ds->PlaylistChanged.connect (bind (slot (*this, &StreamView::playlist_changed), ds)); +} + +void +StreamView::playlist_modified () +{ + ENSURE_GUI_THREAD (slot (*this, &StreamView::playlist_modified)); + + /* if the playlist is modified, make sure xfades are on top and all the regionviews are stacked + correctly. + */ + + for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { + region_layered (*i); + } + + for (list::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + gtk_canvas_item_raise_to_top ((*i)->get_canvas_group()); + } +} + +void +StreamView::playlist_changed (DiskStream *ds) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &StreamView::playlist_changed), ds)); + + /* disconnect from old playlist */ + + for (vector::iterator i = playlist_connections.begin(); i != playlist_connections.end(); ++i) { + (*i).disconnect(); + } + + playlist_connections.clear(); + undisplay_diskstream (); + + /* draw it */ + + redisplay_diskstream (); + + /* catch changes */ + + playlist_connections.push_back (ds->playlist()->RegionAdded.connect (slot (*this, &StreamView::add_region_view))); + playlist_connections.push_back (ds->playlist()->RegionRemoved.connect (slot (*this, &StreamView::remove_region_view))); + playlist_connections.push_back (ds->playlist()->StateChanged.connect (slot (*this, &StreamView::playlist_state_changed))); + playlist_connections.push_back (ds->playlist()->Modified.connect (slot (*this, &StreamView::playlist_modified))); + playlist_connections.push_back (ds->playlist()->NewCrossfade.connect (slot (*this, &StreamView::add_crossfade))); +} + +void +StreamView::add_crossfade (Crossfade *crossfade) +{ + AudioRegionView* lview = 0; + AudioRegionView* rview = 0; + + ENSURE_GUI_THREAD (bind (slot (*this, &StreamView::add_crossfade), crossfade)); + + /* first see if we already have a CrossfadeView for this Crossfade */ + + for (list::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + if (&(*i)->crossfade == crossfade) { + if (!crossfades_visible) { + (*i)->hide(); + } else { + (*i)->show (); + } + (*i)->set_valid (true); + return; + } + } + + /* create a new one */ + + for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { + if (!lview && &((*i)->region) == &crossfade->out()) { + lview = *i; + } + if (!rview && &((*i)->region) == &crossfade->in()) { + rview = *i; + } + } + + CrossfadeView *cv = new CrossfadeView (GTK_CANVAS_GROUP(_trackview.canvas_display), + _trackview, + *crossfade, + _samples_per_unit, + region_color, + *lview, *rview); + + crossfade->Invalidated.connect (slot (*this, &StreamView::remove_crossfade)); + crossfade_views.push_back (cv); + + if (!crossfades_visible) { + cv->hide (); + } +} + +void +StreamView::remove_crossfade (Crossfade *xfade) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &StreamView::remove_crossfade), xfade)); + + for (list::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + if (&(*i)->crossfade == xfade) { + delete *i; + crossfade_views.erase (i); + break; + } + } +} + +void +StreamView::playlist_state_changed (Change ignored) +{ + ENSURE_GUI_THREAD (bind (slot (*this, &StreamView::playlist_state_changed), ignored)); + + redisplay_diskstream (); +} + +void +StreamView::redisplay_diskstream () +{ + list::iterator i, tmp; + list::iterator xi, tmpx; + + for (i = region_views.begin(); i != region_views.end(); ++i) { + (*i)->set_valid (false); + } + + for (xi = crossfade_views.begin(); xi != crossfade_views.end(); ++xi) { + (*xi)->set_valid (false); + if ((*xi)->visible()) { + (*xi)->show (); + } + } + + if (_trackview.is_audio_track()) { + _trackview.get_diskstream()->playlist()->foreach_region (this, &StreamView::add_region_view); + _trackview.get_diskstream()->playlist()->foreach_crossfade (this, &StreamView::add_crossfade); + } + + for (i = region_views.begin(); i != region_views.end(); ) { + tmp = i; + tmp++; + + if (!(*i)->is_valid()) { + delete *i; + region_views.erase (i); + } + + i = tmp; + } + + for (xi = crossfade_views.begin(); xi != crossfade_views.end();) { + tmpx = xi; + tmpx++; + + if (!(*xi)->valid()) { + delete *xi; + crossfade_views.erase (xi); + } + + xi = tmpx; + } + + /* now fix layering */ + + playlist_modified (); +} + +void +StreamView::diskstream_changed (void *src_ignored) +{ + AudioTrack *at; + + if ((at = _trackview.audio_track()) != 0) { + DiskStream& ds = at->disk_stream(); + /* XXX grrr: when will SigC++ allow me to bind references? */ + Gtkmmext::UI::instance()->call_slot (bind (slot (*this, &StreamView::display_diskstream), &ds)); + } else { + Gtkmmext::UI::instance()->call_slot (slot (*this, &StreamView::undisplay_diskstream)); + } +} + +void +StreamView::apply_color (GdkColor& color, ColorTarget target) + +{ + list::iterator i; + + switch (target) { + case RegionColor: + region_color = color; + for (i = region_views.begin(); i != region_views.end(); ++i) { + (*i)->set_color (region_color); + } + // stream_base_color = RGBA_TO_UINT (color.red/256, color.green/256, color.blue/256, 255); + // gtk_canvas_item_set (canvas_rect, "fill_color_rgba", stream_base_color, NULL); + break; + + case StreamBaseColor: + // stream_base_color = RGBA_TO_UINT (color.red/256, color.green/256, color.blue/256, 255); + // gtk_canvas_item_set (canvas_rect, "fill_color_rgba", stream_base_color, NULL); + break; + } +} + +void +StreamView::set_show_waveforms (bool yn) +{ + for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { + (*i)->set_waveform_visible (yn); + } +} + +void +StreamView::set_selected_regionviews (AudioRegionSelection& regions) +{ + bool selected; + + for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { + + selected = false; + + for (AudioRegionSelection::iterator ii = regions.begin(); ii != regions.end(); ++ii) { + if (*i == *ii) { + selected = true; + } + } + + (*i)->set_selected (selected, this); + } +} + +void +StreamView::get_selectables (jack_nframes_t start, jack_nframes_t end, list& results) +{ + for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { + if ((*i)->region.coverage(start, end) != OverlapNone) { + results.push_back (*i); + } + } +} + +void +StreamView::get_inverted_selectables (Selection& sel, list& results) +{ + for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { + if (!sel.audio_regions.contains (*i)) { + results.push_back (*i); + } + } +} + +void +StreamView::set_waveform_shape (WaveformShape shape) +{ + for (AudioRegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) { + (*i)->set_waveform_shape (shape); + } +} + +void +StreamView::region_layered (AudioRegionView* rv) +{ + gtk_canvas_item_lower_to_bottom (rv->get_canvas_group()); + + /* don't ever leave it at the bottom, since then it doesn't + get events - the parent group does instead ... + */ + + gtk_canvas_item_raise (rv->get_canvas_group(), rv->region.layer() + 1); +} + +void +StreamView::rec_enable_changed (void *src) +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &StreamView::setup_rec_box)); +} + +void +StreamView::sess_rec_enable_changed () +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &StreamView::setup_rec_box)); +} + +void +StreamView::transport_changed() +{ + Gtkmmext::UI::instance()->call_slot (slot (*this, &StreamView::setup_rec_box)); +} + +void +StreamView::setup_rec_box () +{ + // cerr << _trackview.name() << " streamview SRB\n"; + + if (_trackview.session().transport_rolling()) { + + // cerr << "\trolling\n"; + + if (!rec_active + && _trackview.session().record_status() == Session::Recording + && _trackview.get_diskstream()->record_enabled()) { + + if (use_rec_regions && rec_regions.size() == rec_rects.size()) { + /* add a new region, but don't bother if they set use_rec_regions mid-record */ + + AudioRegion::SourceList sources; + + for (list::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) { + (*prc).disconnect(); + } + peak_ready_connections.clear(); + + for (uint32_t n=0; n < _trackview.get_diskstream()->n_channels(); ++n) { + Source *src = (Source *) _trackview.get_diskstream()->write_source (n); + if (src) { + sources.push_back (src); + peak_ready_connections.push_back (src->PeakRangeReady.connect (bind (slot (*this, &StreamView::rec_peak_range_ready), src))); + } + } + + // handle multi + + jack_nframes_t start = 0; + if (rec_regions.size() > 0) { + start = rec_regions.back()->start() + _trackview.get_diskstream()->get_captured_frames(rec_regions.size()-1); + } + + AudioRegion * region = new AudioRegion(sources, start, 1 , "", 0, (Region::Flag)(Region::DefaultFlags | Region::DoNotSaveState), false); + region->set_position (_trackview.session().transport_frame(), this); + rec_regions.push_back (region); + /* catch it if it goes away */ + region->GoingAway.connect (slot (*this, &StreamView::remove_rec_region)); + + /* we add the region later */ + } + + /* start a new rec box */ + + AudioTrack* at; + + at = _trackview.audio_track(); /* we know what it is already */ + DiskStream& ds = at->disk_stream(); + jack_nframes_t frame_pos = ds.current_capture_start (); + gdouble xstart = _trackview.editor.frame_to_pixel (frame_pos); + gdouble xend = xstart; + + GtkCanvasItem * rec_rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_group), + gtk_canvas_simplerect_get_type(), + "x1", xstart, + "y1", 1.0, + "x2", xend, + "y2", (double) _trackview.height - 1, + "outline_color_rgba", color_map[cRecordingRectOutline], + "fill_color_rgba", color_map[cRecordingRectFill], + NULL); + + RecBoxInfo recbox; + recbox.rectangle = rec_rect; + recbox.start = _trackview.session().transport_frame(); + recbox.length = 0; + + rec_rects.push_back (recbox); + + screen_update_connection.disconnect(); + screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (slot (*this, &StreamView::update_rec_box)); + rec_updating = true; + rec_active = true; + + } else if (rec_active && + (_trackview.session().record_status() != Session::Recording || + !_trackview.get_diskstream()->record_enabled())) { + + screen_update_connection.disconnect(); + rec_active = false; + rec_updating = false; + + } + + } else { + + // cerr << "\tNOT rolling, rec_rects = " << rec_rects.size() << " rec_regions = " << rec_regions.size() << endl; + + if (!rec_rects.empty() || !rec_regions.empty()) { + + /* disconnect rapid update */ + screen_update_connection.disconnect(); + + for (list::iterator prc = peak_ready_connections.begin(); prc != peak_ready_connections.end(); ++prc) { + (*prc).disconnect(); + } + peak_ready_connections.clear(); + + rec_updating = false; + rec_active = false; + last_rec_peak_frame = 0; + + /* remove temp regions */ + for (list::iterator iter=rec_regions.begin(); iter != rec_regions.end(); ) + { + list::iterator tmp; + + tmp = iter; + ++tmp; + + /* this will trigger the remove_region_view */ + delete *iter; + + iter = tmp; + } + + rec_regions.clear(); + + // cerr << "\tclear " << rec_rects.size() << " rec rects\n"; + + + /* transport stopped, clear boxes */ + for (vector::iterator iter=rec_rects.begin(); iter != rec_rects.end(); ++iter) { + RecBoxInfo &rect = (*iter); + gtk_object_destroy (GTK_OBJECT(rect.rectangle)); + } + + rec_rects.clear(); + + } + } +} + + +void +StreamView::update_rec_box () +{ + /* only update the last box */ + if (rec_active && rec_rects.size() > 0) { + RecBoxInfo & rect = rec_rects.back(); + jack_nframes_t at = _trackview.get_diskstream()->current_capture_end(); + + rect.length = at - rect.start; + + gdouble xstart = _trackview.editor.frame_to_pixel ( rect.start ); + gdouble xend = _trackview.editor.frame_to_pixel ( at ); + + gtk_canvas_item_set (rect.rectangle, "x1", xstart, NULL); + gtk_canvas_item_set (rect.rectangle, "x2", xend, NULL); + } +} + +AudioRegionView* +StreamView::find_view (const AudioRegion& region) +{ + for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { + + if (&(*i)->region == ®ion) { + return *i; + } + } + return 0; +} + +void +StreamView::foreach_regionview (SigC::Slot1 slot) +{ + for (list::iterator i = region_views.begin(); i != region_views.end(); ++i) { + slot (*i); + } +} + +void +StreamView::foreach_crossfadeview (void (CrossfadeView::*pmf)(void)) +{ + for (list::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + ((*i)->*pmf) (); + } +} + +void +StreamView::rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, Source * src) +{ + // this is called from the peak building thread + + ENSURE_GUI_THREAD(bind (slot (*this, &StreamView::rec_peak_range_ready), start, cnt, src)); + + if (rec_peak_ready_map.size() == 0 || start+cnt > last_rec_peak_frame) { + last_rec_peak_frame = start + cnt; + } + + rec_peak_ready_map[src] = true; + + if (rec_peak_ready_map.size() == _trackview.get_diskstream()->n_channels()) { + this->update_rec_regions (); + rec_peak_ready_map.clear(); + } +} + +void +StreamView::update_rec_regions () +{ + if (use_rec_regions) { + + uint32_t n = 0; + + for (list::iterator iter = rec_regions.begin(); iter != rec_regions.end(); n++) { + + list::iterator tmp; + + tmp = iter; + ++tmp; + + if ((GTK_OBJECT_FLAGS(GTK_OBJECT(rec_rects[n].rectangle)) & GTK_CANVAS_ITEM_VISIBLE) == 0) { + /* rect already hidden, this region is done */ + iter = tmp; + continue; + } + + AudioRegion * region = (*iter); + jack_nframes_t origlen = region->length(); + + if (region == rec_regions.back() && rec_active) { + + if (last_rec_peak_frame > region->start()) { + + jack_nframes_t nlen = last_rec_peak_frame - region->start(); + + if (nlen != region->length()) { + + region->freeze (); + region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this); + region->set_length (nlen, this); + region->thaw ("updated"); + + if (origlen == 1) { + /* our special initial length */ + add_region_view_internal (region, false); + } + + /* also update rect */ + GtkCanvasItem * rect = rec_rects[n].rectangle; + gdouble xend = _trackview.editor.frame_to_pixel (region->position() + region->length()); + gtk_canvas_item_set (rect, "x2", xend, NULL); + } + } + + } else { + + jack_nframes_t nlen = _trackview.get_diskstream()->get_captured_frames(n); + + if (nlen != region->length()) { + + if (region->source(0).length() >= region->start() + nlen) { + + region->freeze (); + region->set_position (_trackview.get_diskstream()->get_capture_start_frame(n), this); + region->set_length (nlen, this); + region->thaw ("updated"); + + if (origlen == 1) { + /* our special initial length */ + add_region_view_internal (region, false); + } + + /* also hide rect */ + GtkCanvasItem * rect = rec_rects[n].rectangle; + gtk_canvas_item_hide (rect); + + } + } + } + + iter = tmp; + } + } +} + +void +StreamView::show_all_xfades () +{ + foreach_crossfadeview (&CrossfadeView::show); + crossfades_visible = true; +} + +void +StreamView::hide_all_xfades () +{ + foreach_crossfadeview (&CrossfadeView::hide); + crossfades_visible = false; +} + +void +StreamView::hide_xfades_involving (AudioRegionView& rv) +{ + for (list::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + if ((*i)->crossfade.involves (rv.region)) { + (*i)->fake_hide (); + } + } +} + +void +StreamView::reveal_xfades_involving (AudioRegionView& rv) +{ + for (list::iterator i = crossfade_views.begin(); i != crossfade_views.end(); ++i) { + if ((*i)->crossfade.involves (rv.region) && (*i)->visible()) { + (*i)->show (); + } + } +} diff --git a/gtk2_ardour/streamview.h b/gtk2_ardour/streamview.h new file mode 100644 index 0000000000..8d9162c8ab --- /dev/null +++ b/gtk2_ardour/streamview.h @@ -0,0 +1,171 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_streamview_h__ +#define __ardour_streamview_h__ + +#include +#include +#include + +#include +#include + +#include +#include "enums.h" + +namespace ARDOUR { + class Route; + class DiskStream; + class Crossfade; + class PeakData; + class AudioRegion; + class Source; +} + +struct RecBoxInfo { + GtkCanvasItem* rectangle; + jack_nframes_t start; + jack_nframes_t length; +}; + +class PublicEditor; +class Selectable; +class AudioTimeAxisView; +class AudioRegionView; +class AudioRegionSelection; +class CrossfadeView; +class Selection; + +class StreamView : public SigC::Object +{ + public: + StreamView (AudioTimeAxisView&); + ~StreamView (); + + void set_waveform_shape (WaveformShape); + + AudioTimeAxisView& trackview() { return _trackview; } + + void set_zoom_all(); + + int set_height (gdouble); + int set_position (gdouble x, gdouble y); + + int set_samples_per_unit (gdouble spp); + gdouble get_samples_per_unit () { return _samples_per_unit; } + + int set_amplitude_above_axis (gdouble app); + gdouble get_amplitude_above_axis () { return _amplitude_above_axis; } + + void set_show_waveforms (bool yn); + void set_show_waveforms_recording (bool yn) { use_rec_regions = yn; } + + GtkCanvasItem* canvas_item() { return canvas_group; } + + SigC::Signal1 AudioRegionViewAdded; + + enum ColorTarget { + RegionColor, + StreamBaseColor + }; + + void apply_color (GdkColor&, ColorTarget t); + void set_selected_regionviews (AudioRegionSelection&); + void get_selectables (jack_nframes_t start, jack_nframes_t end, list&); + void get_inverted_selectables (Selection&, list& results); + GdkColor get_region_color () const { return region_color; } + + void foreach_regionview (SigC::Slot1 slot); + void foreach_crossfadeview (void (CrossfadeView::*pmf)(void)); + + void attach (); + + void region_layered (AudioRegionView*); + + AudioRegionView* find_view (const ARDOUR::AudioRegion&); + + void show_all_xfades (); + void hide_all_xfades (); + void hide_xfades_involving (AudioRegionView&); + void reveal_xfades_involving (AudioRegionView&); + + private: + AudioTimeAxisView& _trackview; + + GtkCanvasItem* canvas_group; + GtkCanvasItem* canvas_rect; /* frame around the whole thing */ + + typedef list AudioRegionViewList; + AudioRegionViewList region_views; + + typedef list CrossfadeViewList; + CrossfadeViewList crossfade_views; + + double _samples_per_unit; + double _amplitude_above_axis; + + SigC::Connection screen_update_connection; + vector rec_rects; + list rec_regions; + bool rec_updating; + bool rec_active; + bool use_rec_regions; + list peak_ready_connections; + jack_nframes_t last_rec_peak_frame; + map rec_peak_ready_map; + + void update_rec_box (); + void transport_changed(); + void rec_enable_changed(void* src = 0); + void sess_rec_enable_changed(); + void setup_rec_box (); + void rec_peak_range_ready (jack_nframes_t start, jack_nframes_t cnt, ARDOUR::Source* src); + void update_rec_regions (); + + void add_region_view (ARDOUR::Region*); + void add_region_view_internal (ARDOUR::Region*, bool wait_for_waves); + void remove_region_view (ARDOUR::Region* ); + void remove_rec_region (ARDOUR::Region*); + void remove_audio_region_view (ARDOUR::AudioRegion* ); + void remove_audio_rec_region (ARDOUR::AudioRegion*); + + void display_diskstream (ARDOUR::DiskStream* ); + void undisplay_diskstream (); + void redisplay_diskstream (); + void diskstream_changed (void* ); + void playlist_state_changed (ARDOUR::Change); + void playlist_changed (ARDOUR::DiskStream* ); + void playlist_modified (); + + bool crossfades_visible; + void add_crossfade (ARDOUR::Crossfade*); + void remove_crossfade (ARDOUR::Crossfade*); + + /* XXX why are these different? */ + + GdkColor region_color; + uint32_t stream_base_color; + + vector playlist_connections; + SigC::Connection playlist_change_connection; +}; + +#endif /* __ardour_streamview_h__ */ diff --git a/gtk2_ardour/strip_selection.h b/gtk2_ardour/strip_selection.h new file mode 100644 index 0000000000..5204873c7a --- /dev/null +++ b/gtk2_ardour/strip_selection.h @@ -0,0 +1,10 @@ +#ifndef __ardour_gtk_strip_selection_h__ +#define __ardour_gtk_strip_selection_h__ + +#include + +class MixerStrip; + +struct MixerStripSelection : list {}; + +#endif /* __ardour_gtk_strip_selection_h__ */ diff --git a/gtk2_ardour/tempo_dialog.cc b/gtk2_ardour/tempo_dialog.cc new file mode 100644 index 0000000000..3428985518 --- /dev/null +++ b/gtk2_ardour/tempo_dialog.cc @@ -0,0 +1,333 @@ +#include // for snprintf, grrr + +#include + +#include "tempo_dialog.h" + +#include "i18n.h" + +using namespace Gtk; +using namespace ARDOUR; + +TempoDialog::TempoDialog (TempoMap& map, jack_nframes_t frame, string action) + : ArdourDialog ("tempo dialog"), + bpm_frame (_("Beats per minute")), + ok_button (action), + cancel_button (_("Cancel")), + when_bar_label (_("Bar")), + when_beat_label (_("Beat")), + when_table (2, 2), + when_frame (_("Location")) +{ + BBT_Time when; + Tempo tempo (map.tempo_at (frame)); + map.bbt_time (frame, when); + + init (when, tempo.beats_per_minute(), true); +} + +TempoDialog::TempoDialog (TempoSection& section, string action) + : ArdourDialog ("tempo dialog"), + bpm_frame (_("Beats per minute")), + ok_button (action), + cancel_button (_("Cancel")), + when_bar_label (_("Bar")), + when_beat_label (_("Beat")), + when_table (2, 2), + when_frame (_("Location")) +{ + init (section.start(), section.beats_per_minute(), section.movable()); +} + +void +TempoDialog::init (const BBT_Time& when, double bpm, bool movable) +{ + snprintf (buf, sizeof (buf), "%.2f", bpm); + bpm_entry.set_text (buf); + bpm_entry.select_region (0, -1); + + hspacer1.set_border_width (5); + hspacer1.pack_start (bpm_entry, false, false); + vspacer1.set_border_width (5); + vspacer1.pack_start (hspacer1, false, false); + + bpm_frame.add (vspacer1); + + button_box.set_border_width (10); + button_box.set_spacing (5); + button_box.set_homogeneous (true); + button_box.pack_start (ok_button); + button_box.pack_start (cancel_button); + + vpacker.set_border_width (10); + vpacker.set_spacing (5); + + if (movable) { + snprintf (buf, sizeof (buf), "%" PRIu32, when.bars); + when_bar_entry.set_text (buf); + snprintf (buf, sizeof (buf), "%" PRIu32, when.beats); + when_beat_entry.set_text (buf); + + when_bar_entry.set_name ("MetricEntry"); + when_beat_entry.set_name ("MetricEntry"); + + when_bar_label.set_name ("MetricLabel"); + when_beat_label.set_name ("MetricLabel"); + + Gtkmmext::set_usize_to_display_given_text (when_bar_entry, "999g", 5, 7); + Gtkmmext::set_usize_to_display_given_text (when_beat_entry, "999g", 5, 7); + + when_table.set_homogeneous (true); + when_table.set_row_spacings (2); + when_table.set_col_spacings (2); + when_table.set_border_width (5); + + when_table.attach (when_bar_label, 0, 1, 0, 1, 0, GTK_FILL|GTK_EXPAND); + when_table.attach (when_bar_entry, 0, 1, 1, 2, 0, GTK_FILL|GTK_EXPAND); + + when_table.attach (when_beat_label, 1, 2, 0, 1, 0, 0); + when_table.attach (when_beat_entry, 1, 2, 1, 2, 0, 0); + + when_frame.set_name ("MetricDialogFrame"); + when_frame.add (when_table); + + vpacker.pack_start (when_frame, false, false); + } + + vpacker.pack_start (bpm_frame, false, false); + vpacker.pack_start (button_box, false, false); + + bpm_frame.set_name ("MetricDialogFrame"); + bpm_entry.set_name ("MetricEntry"); + ok_button.set_name ("MetricButton"); + cancel_button.set_name ("MetricButton"); + + add (vpacker); + set_name ("MetricDialog"); + + set_keyboard_input(true); +} + +double +TempoDialog::get_bpm () +{ + double bpm; + + if (sscanf (bpm_entry.get_text().c_str(), "%lf", &bpm) != 1) { + return 0; + } + + return bpm; +} + +bool +TempoDialog::get_bbt_time (BBT_Time& requested) +{ + if (sscanf (when_bar_entry.get_text().c_str(), "%" PRIu32, &requested.bars) != 1) { + return false; + } + + if (sscanf (when_beat_entry.get_text().c_str(), "%" PRIu32, &requested.beats) != 1) { + return false; + } + + return true; +} + + +MeterDialog::MeterDialog (TempoMap& map, jack_nframes_t frame, string action) + : ArdourDialog ("meter dialog"), + note_frame (_("Meter denominator")), + bpb_frame (_("Beats per bar")), + ok_button (action), + cancel_button (_("Cancel")), + when_bar_label (_("Bar")), + when_beat_label (_("Beat")), + when_frame (_("Location")) +{ + BBT_Time when; + frame = map.round_to_bar(frame,0); + Meter meter (map.meter_at(frame)); + + map.bbt_time (frame, when); + init (when, meter.beats_per_bar(), meter.note_divisor(), true); +} + +MeterDialog::MeterDialog (MeterSection& section, string action) + : ArdourDialog ("meter dialog"), + note_frame (_("Meter denominator")), + bpb_frame (_("Beats per bar")), + ok_button (action), + cancel_button (_("Cancel")), + when_bar_label (_("Bar")), + when_beat_label (_("Beat")), + when_frame (_("Location")) +{ + init (section.start(), section.beats_per_bar(), section.note_divisor(), section.movable()); +} + +void +MeterDialog::init (const BBT_Time& when, double bpb, double note_type, bool movable) +{ + snprintf (buf, sizeof (buf), "%.2f", bpb); + bpb_entry.set_text (buf); + bpb_entry.select_region (0, -1); + Gtkmmext::set_usize_to_display_given_text (bpb_entry, "999999g", 5, 5); + + + strings.push_back (_("whole (1)")); + strings.push_back (_("second (2)")); + strings.push_back (_("third (3)")); + strings.push_back (_("quarter (4)")); + strings.push_back (_("eighth (8)")); + strings.push_back (_("sixteenth (16)")); + strings.push_back (_("thirty-second (32)")); + + note_types.set_popdown_strings (strings); + + if (note_type==1.0f) + note_types.get_entry()->set_text(_("whole (1)")); + else if (note_type==2.0f) + note_types.get_entry()->set_text(_("second (2)")); + else if (note_type==3.0f) + note_types.get_entry()->set_text(_("third (3)")); + else if (note_type==4.0f) + note_types.get_entry()->set_text(_("quarter (4)")); + else if (note_type==8.0f) + note_types.get_entry()->set_text(_("eighth (8)")); + else if (note_type==16.0f) + note_types.get_entry()->set_text(_("sixteenth (16)")); + else if (note_type==32.0f) + note_types.get_entry()->set_text(_("thirty-second (32)")); + else + note_types.get_entry()->set_text(_("quarter (4)")); + + /* strings.back() just happens to be the longest one to display */ + Gtkmmext::set_usize_to_display_given_text (*(note_types.get_entry()), strings.back(), 7, 7); + + hspacer1.set_border_width (5); + hspacer1.pack_start (note_types, false, false); + vspacer1.set_border_width (5); + vspacer1.pack_start (hspacer1, false, false); + + hspacer2.set_border_width (5); + hspacer2.pack_start (bpb_entry, false, false); + vspacer2.set_border_width (5); + vspacer2.pack_start (hspacer2, false, false); + + note_frame.add (vspacer1); + bpb_frame.add (vspacer2); + + button_box.set_border_width (10); + button_box.set_spacing (5); + button_box.set_homogeneous (true); + button_box.pack_start (ok_button); + button_box.pack_start (cancel_button); + + vpacker.set_border_width (10); + vpacker.set_spacing (5); + + if (movable) { + snprintf (buf, sizeof (buf), "%" PRIu32, when.bars); + when_bar_entry.set_text (buf); + snprintf (buf, sizeof (buf), "%" PRIu32, when.beats); + when_beat_entry.set_text (buf); + + when_bar_entry.set_name ("MetricEntry"); + when_beat_entry.set_name ("MetricEntry"); + + when_bar_label.set_name ("MetricLabel"); + when_beat_label.set_name ("MetricLabel"); + + Gtkmmext::set_usize_to_display_given_text (when_bar_entry, "999g", 5, 7); + Gtkmmext::set_usize_to_display_given_text (when_beat_entry, "999g", 5, 7); + + when_table.set_homogeneous (true); + when_table.set_row_spacings (2); + when_table.set_col_spacings (2); + when_table.set_border_width (5); + + when_table.attach (when_bar_label, 0, 1, 0, 1, 0, GTK_FILL|GTK_EXPAND); + when_table.attach (when_bar_entry, 0, 1, 1, 2, 0, GTK_FILL|GTK_EXPAND); + + when_table.attach (when_beat_label, 1, 2, 0, 1, 0, 0); + when_table.attach (when_beat_entry, 1, 2, 1, 2, 0, 0); + + when_frame.set_name ("MetricDialogFrame"); + when_frame.add (when_table); + + vpacker.pack_start (when_frame, false, false); + } + + vpacker.pack_start (bpb_frame, false, false); + vpacker.pack_start (note_frame, false, false); + vpacker.pack_start (button_box, false, false); + + bpb_frame.set_name ("MetricDialogFrame"); + note_frame.set_name ("MetricDialogFrame"); + note_types.get_entry()->set_name ("MetricEntry"); + bpb_entry.set_name ("MetricEntry"); + ok_button.set_name ("MetricButton"); + cancel_button.set_name ("MetricButton"); + + add (vpacker); + set_name ("MetricDialog"); + + set_keyboard_input(true); +} + +double +MeterDialog::get_bpb () +{ + double bpb = 0; + + if (sscanf (bpb_entry.get_text().c_str(), "%lf", &bpb) != 1) { + return 0; + } + + return bpb; +} + +double +MeterDialog::get_note_type () +{ + double note_type = 0; + vector::iterator i; + string text = note_types.get_entry()->get_text(); + + for (i = strings.begin(); i != strings.end(); ++i) { + if (text == *i) { + if (sscanf (text.c_str(), "%*[^0-9]%lf", ¬e_type) != 1) { + error << compose(_("garbaged note type entry (%1)"), text) << endmsg; + return 0; + } else { + break; + } + } + } + + if (i == strings.end()) { + if (sscanf (text.c_str(), "%lf", ¬e_type) != 1) { + error << compose(_("incomprehensible note type entry (%1)"), text) << endmsg; + return 0; + } + } + + return note_type; +} + +bool +MeterDialog::get_bbt_time (BBT_Time& requested) +{ + requested.ticks = 0; + + if (sscanf (when_bar_entry.get_text().c_str(), "%" PRIu32, &requested.bars) != 1) { + return false; + } + + if (sscanf (when_beat_entry.get_text().c_str(), "%" PRIu32, &requested.beats) != 1) { + return false; + } + + return true; +} diff --git a/gtk2_ardour/tempo_dialog.h b/gtk2_ardour/tempo_dialog.h new file mode 100644 index 0000000000..b091007c7d --- /dev/null +++ b/gtk2_ardour/tempo_dialog.h @@ -0,0 +1,70 @@ +#ifndef __ardour_gtk_tempo_dialog_h__ +#define __ardour_gtk_tempo_dialog_h__ + +#include +#include +#include + +#include "ardour_dialog.h" + +struct TempoDialog : public ArdourDialog +{ + Gtk::Entry bpm_entry; + Gtk::Frame bpm_frame; + Gtk::VBox vpacker; + Gtk::Button ok_button; + Gtk::Button cancel_button; + Gtk::HBox button_box; + Gtk::HBox hspacer1; + Gtk::VBox vspacer1; + Gtk::Entry when_bar_entry; + Gtk::Entry when_beat_entry; + Gtk::Label when_bar_label; + Gtk::Label when_beat_label; + Gtk::Table when_table; + Gtk::Frame when_frame; + char buf[64]; + + TempoDialog (ARDOUR::TempoMap&, jack_nframes_t, string action); + TempoDialog (ARDOUR::TempoSection&, string action); + + double get_bpm (); + bool get_bbt_time (ARDOUR::BBT_Time&); + + private: + void init (const ARDOUR::BBT_Time& start, double, bool); +}; + +struct MeterDialog : public ArdourDialog +{ + Gtk::Entry bpb_entry; + Gtk::Combo note_types; + vector strings; + Gtk::Frame note_frame; + Gtk::Frame bpb_frame; + Gtk::VBox vpacker; + Gtk::Button ok_button; + Gtk::Button cancel_button; + Gtk::HBox button_box; + Gtk::HBox hspacer1, hspacer2; + Gtk::VBox vspacer1, vspacer2; + Gtk::Entry when_bar_entry; + Gtk::Entry when_beat_entry; + Gtk::Label when_bar_label; + Gtk::Label when_beat_label; + Gtk::Table when_table; + Gtk::Frame when_frame; + char buf[64]; + + MeterDialog (ARDOUR::TempoMap&, jack_nframes_t, string action); + MeterDialog (ARDOUR::MeterSection&, string action); + + double get_bpb (); + double get_note_type (); + bool get_bbt_time (ARDOUR::BBT_Time&); + + private: + void init (const ARDOUR::BBT_Time&, double, double, bool); +}; + +#endif /* __ardour_gtk_tempo_dialog_h__ */ diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc new file mode 100644 index 0000000000..b0573714ad --- /dev/null +++ b/gtk2_ardour/time_axis_view.cc @@ -0,0 +1,803 @@ +/* + Copyright (C) 2000 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ardour_ui.h" +#include "public_editor.h" +#include "time_axis_view.h" +#include "canvas-simplerect.h" +#include "selection.h" +#include "keyboard.h" +#include "rgb_macros.h" + +#include "i18n.h" + +using namespace Gtk; +using namespace SigC; +using namespace ARDOUR; +using namespace Editing; + +const double trim_handle_size = 6.0; /* pixels */ + +TimeAxisView::TimeAxisView(ARDOUR::Session& sess, PublicEditor& ed, TimeAxisView* rent, Gtk::Widget *canvas) + : AxisView(sess), + editor(ed), + controls_table (2, 9) +{ + canvas_display = gtk_canvas_item_new (gtk_canvas_root(GTK_CANVAS(canvas->gtkobj())), + gtk_canvas_group_get_type(), + "x", 0.0, + "y", 0.0, + NULL); + + selection_group = gtk_canvas_item_new (GTK_CANVAS_GROUP(canvas_display), + gtk_canvas_group_get_type (), + NULL); + gtk_canvas_item_hide (selection_group); + + control_parent = 0; + display_menu = 0; + size_menu = 0; + _marked_for_display = false; + _hidden = false; + height = 0; + effective_height = 0; + parent = rent; + _has_state = false; + + /* + Create the standard LHS Controls + We create the top-level container and name add the name label here, + subclasses can add to the layout as required + */ + + name_entry.set_name ("EditorTrackNameDisplay"); + name_entry.button_release_event.connect (slot (*this, &TimeAxisView::name_entry_button_release)); + name_entry.button_press_event.connect (slot (*this, &TimeAxisView::name_entry_button_press)); + + name_entry.focus_in_event.connect (slot (ARDOUR_UI::generic_focus_in_event)); + name_entry.focus_out_event.connect (slot (ARDOUR_UI::generic_focus_out_event)); + + Gtkmmext::set_usize_to_display_given_text (name_entry, N_("gTortnam"), 10, 10); // just represents a short name + + name_label.set_name ("TrackLabel"); + name_label.set_alignment (0.0, 0.5); + + // name_hbox.set_border_width (2); + // name_hbox.set_spacing (5); + + /* typically, either name_label OR name_entry are visible, + but not both. its up to derived classes to show/hide them as they + wish. + */ + + name_hbox.pack_start (name_label, true, true); + name_hbox.pack_start (name_entry, true, true); + name_hbox.show (); + + controls_table.set_border_width (2); + controls_table.set_row_spacings (0); + controls_table.set_col_spacings (0); + controls_table.set_homogeneous (true); + controls_table.show (); + + controls_table.attach (name_hbox, 0, 5, 0, 1, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + + controls_table.show (); + + controls_vbox.pack_start (controls_table, false, false); + controls_vbox.show (); + + controls_ebox.set_name ("TimeAxisViewControlsBaseUnselected"); + controls_ebox.add (controls_vbox); + controls_ebox.add_events (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK); + controls_ebox.set_flags (GTK_CAN_FOCUS); + + controls_ebox.button_release_event.connect (slot (*this, &TimeAxisView::controls_ebox_button_release)); + + controls_lhs_pad.set_name ("TimeAxisViewControlsPadding"); + controls_hbox.pack_start (controls_lhs_pad,false,false); + controls_hbox.pack_start (controls_ebox,true,true); + controls_hbox.show (); + + controls_frame.add (controls_hbox); + controls_frame.set_name ("TimeAxisViewControlsBaseUnselected"); + controls_frame.set_shadow_type (GTK_SHADOW_OUT); +} + +TimeAxisView::~TimeAxisView() +{ + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + delete *i; + } + + for (list::iterator i = free_selection_rects.begin(); i != free_selection_rects.end(); ++i) { + gtk_object_destroy (GTK_OBJECT((*i)->rect)); + gtk_object_destroy (GTK_OBJECT((*i)->start_trim)); + gtk_object_destroy (GTK_OBJECT((*i)->end_trim)); + } + + for (list::iterator i = used_selection_rects.begin(); i != used_selection_rects.end(); ++i) { + gtk_object_destroy (GTK_OBJECT((*i)->rect)); + gtk_object_destroy (GTK_OBJECT((*i)->start_trim)); + gtk_object_destroy (GTK_OBJECT((*i)->end_trim)); + } + + if (selection_group) { + gtk_object_destroy (GTK_OBJECT (selection_group)); + selection_group = 0; + } + + if (canvas_display) { + gtk_object_destroy (GTK_OBJECT (canvas_display)); + canvas_display = 0; + } + + if (display_menu) { + delete display_menu; + display_menu = 0; + } + + if (size_menu) { + delete size_menu; + size_menu = 0; + } +} + +guint32 +TimeAxisView::show_at (double y, int& nth, VBox *parent) +{ + gdouble ix1, ix2, iy1, iy2; + effective_height = 0; + + if (control_parent) { + control_parent->reorder_child (controls_frame, nth); + } else { + control_parent = parent; + parent->pack_start (controls_frame, false, false); + parent->reorder_child (controls_frame, nth); + } + + controls_frame.show (); + controls_ebox.show (); + + /* the coordinates used here are in the system of the + item's parent ... + */ + + gtk_canvas_item_get_bounds (canvas_display, &ix1, &iy1, &ix2, &iy2); + gtk_canvas_item_i2w (canvas_display->parent, &ix1, &iy1); + if (iy1 < 0) { + iy1 = 0; + } + gtk_canvas_item_move (canvas_display, 0.0, y - iy1); + gtk_canvas_item_show (canvas_display); /* XXX not necessary */ + + y_position = y; + order = nth; + _hidden = false; + + effective_height = height; + + /* now show children */ + + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + + if ((*i)->marked_for_display()) { + gtk_canvas_item_show ((*i)->canvas_display); + } + + if (GTK_OBJECT_FLAGS(GTK_OBJECT((*i)->canvas_display)) & GTK_CANVAS_ITEM_VISIBLE) { + ++nth; + effective_height += (*i)->show_at (y + effective_height, nth, parent); + } + } + + return effective_height; +} + +gint +TimeAxisView::controls_ebox_button_release (GdkEventButton* ev) +{ + switch (ev->button) { + case 1: + selection_click (ev); + break; + + case 3: + popup_display_menu (ev->time); + break; + + case 4: + if (Keyboard::no_modifier_keys_pressed (ev)) { + editor.scroll_tracks_up_line (); + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + step_height (true); + } + break; + + case 5: + if (Keyboard::no_modifier_keys_pressed (ev)) { + editor.scroll_tracks_down_line (); + } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + step_height (false); + } + break; + + + } + + return TRUE; +} + +void +TimeAxisView::selection_click (GdkEventButton* ev) +{ + if (Keyboard::modifier_state_contains (ev->state, Keyboard::Shift)) { + + if (editor.get_selection().selected (this)) { + editor.get_selection().remove (this); + } else { + editor.get_selection().add (this); + } + + } else { + + editor.get_selection().set (this); + } +} + +void +TimeAxisView::hide () +{ + if (_hidden) { + return; + } + + gtk_canvas_item_hide (canvas_display); + controls_frame.hide (); + + if (control_parent) { + control_parent->remove (controls_frame); + control_parent = 0; + } + + y_position = -1; + _hidden = true; + + /* now hide children */ + + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + (*i)->hide (); + } + + Hiding (); +} + +void +TimeAxisView::step_height (bool bigger) +{ + switch (height) { + case Largest: + if (!bigger) set_height (Large); + break; + case Large: + if (bigger) set_height (Largest); + else set_height (Larger); + break; + case Larger: + if (bigger) set_height (Large); + else set_height (Normal); + break; + case Normal: + if (bigger) set_height (Larger); + else set_height (Smaller); + break; + case Smaller: + if (bigger) set_height (Normal); + else set_height (Small); + break; + case Small: + if (bigger) set_height (Smaller); + break; + } +} + + +void +TimeAxisView::set_height (TrackHeight h) +{ + height = (guint32) h; + controls_frame.set_usize (-1, height); + + if (GTK_OBJECT_FLAGS(GTK_OBJECT(selection_group)) & GTK_CANVAS_ITEM_VISIBLE) { + /* resize the selection rect */ + show_selection (editor.get_selection().time); + } + +// for (vector::iterator i = children.begin(); i != children.end(); ++i) { +// (*i)->set_height (h); +// } + +} + + +gint +TimeAxisView::name_entry_button_press (GdkEventButton *ev) +{ + if (ev->button == 3) { + return do_not_propagate (ev); + } + return FALSE; +} + +gint +TimeAxisView::name_entry_button_release (GdkEventButton *ev) +{ + if (ev->button == 3) { + popup_display_menu (ev->time); + return stop_signal (name_entry, "button_release_event"); + } + return FALSE; +} + +void +TimeAxisView::popup_display_menu (guint32 when) +{ + if (display_menu == 0) { + build_display_menu (); + } + display_menu->popup (1, when); +} + +gint +TimeAxisView::size_click (GdkEventButton *ev) +{ + popup_size_menu (ev->time); + return TRUE; +} + +void +TimeAxisView::popup_size_menu (guint32 when) +{ + if (size_menu == 0) { + build_size_menu (); + } + size_menu->popup (1, when); +} + +void +TimeAxisView::set_selected (bool yn) +{ + AxisView::set_selected (yn); + + if (_selected) { + controls_ebox.set_name (controls_base_selected_name); + controls_frame.set_name (controls_base_selected_name); + + /* propagate any existing selection, if the mode is right */ + + if (editor.current_mouse_mode() == Editing::MouseRange && !editor.get_selection().time.empty()) { + show_selection (editor.get_selection().time); + } + + } else { + controls_ebox.set_name (controls_base_unselected_name); + controls_frame.set_name (controls_base_unselected_name); + + hide_selection (); + + /* children will be set for the yn=true case. but when deselecting + the editor only has a list of top-level trackviews, so we + have to do this here. + */ + + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + (*i)->set_selected (false); + } + + + } +} + +void +TimeAxisView::build_size_menu () +{ + using namespace Menu_Helpers; + + size_menu = new Menu; + size_menu->set_name ("ArdourContextMenu"); + MenuList& items = size_menu->items(); + + items.push_back (MenuElem (_("Largest"), bind (slot (*this, &TimeAxisView::set_height), Largest))); + items.push_back (MenuElem (_("Large"), bind (slot (*this, &TimeAxisView::set_height), Large))); + items.push_back (MenuElem (_("Larger"), bind (slot (*this, &TimeAxisView::set_height), Larger))); + items.push_back (MenuElem (_("Normal"), bind (slot (*this, &TimeAxisView::set_height), Normal))); + items.push_back (MenuElem (_("Smaller"), bind (slot (*this, &TimeAxisView::set_height), Smaller))); + items.push_back (MenuElem (_("Small"), bind (slot (*this, &TimeAxisView::set_height), Small))); +} + +void +TimeAxisView::build_display_menu () +{ + using namespace Menu_Helpers; + + display_menu = new Menu; + display_menu->set_name ("ArdourContextMenu"); + + // Just let implementing classes define what goes into the manu +} + +void +TimeAxisView::set_samples_per_unit (double spu) +{ + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + (*i)->set_samples_per_unit (spu); + } +} + +void +TimeAxisView::show_timestretch (jack_nframes_t start, jack_nframes_t end) +{ + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + (*i)->show_timestretch (start, end); + } +} + +void +TimeAxisView::hide_timestretch () +{ + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + (*i)->hide_timestretch (); + } +} + +void +TimeAxisView::show_selection (TimeSelection& ts) +{ + double x1; + double x2; + double y2; + SelectionRect *rect; + + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + (*i)->show_selection (ts); + } + + if (GTK_OBJECT_FLAGS(GTK_OBJECT(selection_group)) & GTK_CANVAS_ITEM_VISIBLE) { + while (!used_selection_rects.empty()) { + free_selection_rects.push_front (used_selection_rects.front()); + used_selection_rects.pop_front(); + gtk_canvas_item_hide (free_selection_rects.front()->rect); + gtk_canvas_item_hide (free_selection_rects.front()->start_trim); + gtk_canvas_item_hide (free_selection_rects.front()->end_trim); + } + gtk_canvas_item_hide (selection_group); + } + + gtk_canvas_item_show (selection_group); + gtk_canvas_item_raise_to_top (selection_group); + + for (list::iterator i = ts.begin(); i != ts.end(); ++i) { + jack_nframes_t start, end, cnt; + + start = (*i).start; + end = (*i).end; + cnt = end - start + 1; + + rect = get_selection_rect ((*i).id); + + x1 = start / editor.get_current_zoom(); + x2 = (start + cnt - 1) / editor.get_current_zoom(); + y2 = height; + + gtk_object_set (GTK_OBJECT(rect->rect), + "x1", x1, + "y1", 1.0, + "x2", x2, + "y2", y2, + NULL); + + // trim boxes are at the top for selections + + if (x2 > x1) { + gtk_object_set (GTK_OBJECT(rect->start_trim), + "x1", x1, + "y1", 1.0, + "x2", x1 + trim_handle_size, + "y2", 1.0 + trim_handle_size, + NULL); + gtk_object_set (GTK_OBJECT(rect->end_trim), + "x1", x2 - trim_handle_size, + "y1", 1.0, + "x2", x2, + "y2", 1.0 + trim_handle_size, + NULL); + gtk_canvas_item_show (rect->start_trim); + gtk_canvas_item_show (rect->end_trim); + } else { + gtk_canvas_item_hide (rect->start_trim); + gtk_canvas_item_hide (rect->end_trim); + } + + gtk_canvas_item_show (rect->rect); + used_selection_rects.push_back (rect); + } +} + +void +TimeAxisView::reshow_selection (TimeSelection& ts) +{ + show_selection (ts); + + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + (*i)->show_selection (ts); + } +} + +void +TimeAxisView::hide_selection () +{ + if (GTK_OBJECT_FLAGS(GTK_OBJECT(selection_group)) & GTK_CANVAS_ITEM_VISIBLE) { + while (!used_selection_rects.empty()) { + free_selection_rects.push_front (used_selection_rects.front()); + used_selection_rects.pop_front(); + gtk_canvas_item_hide (free_selection_rects.front()->rect); + gtk_canvas_item_hide (free_selection_rects.front()->start_trim); + gtk_canvas_item_hide (free_selection_rects.front()->end_trim); + } + gtk_canvas_item_hide (selection_group); + } + + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + (*i)->hide_selection (); + } +} + +void +TimeAxisView::order_selection_trims (GtkCanvasItem *item, bool put_start_on_top) +{ + /* find the selection rect this is for. we have the item corresponding to one + of the trim handles. + */ + + for (list::iterator i = used_selection_rects.begin(); i != used_selection_rects.end(); ++i) { + if ((*i)->start_trim == item || (*i)->end_trim == item) { + + /* make one trim handle be "above" the other so that if they overlap, + the top one is the one last used. + */ + + gtk_canvas_item_raise_to_top ((*i)->rect); + gtk_canvas_item_raise_to_top (put_start_on_top ? (*i)->start_trim : (*i)->end_trim); + gtk_canvas_item_raise_to_top (put_start_on_top ? (*i)->end_trim : (*i)->start_trim); + + break; + } + } +} + +SelectionRect * +TimeAxisView::get_selection_rect (uint32_t id) +{ + SelectionRect *rect; + + /* check to see if we already have a visible rect for this particular selection ID */ + + for (list::iterator i = used_selection_rects.begin(); i != used_selection_rects.end(); ++i) { + if ((*i)->id == id) { + return (*i); + } + } + + /* ditto for the free rect list */ + + for (list::iterator i = free_selection_rects.begin(); i != free_selection_rects.end(); ++i) { + if ((*i)->id == id) { + free_selection_rects.erase (i); + return (*i); + } + } + + /* no existing matching rect, so go get a new one from the free list, or create one if there are none */ + + if (free_selection_rects.empty()) { + + rect = new SelectionRect; + + rect->rect = gtk_canvas_item_new (GTK_CANVAS_GROUP(selection_group), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "y1", 0.0, + "x2", 0.0, + "y2", 0.0, + "fill_color_rgba", color_map[cSelectionRectFill], + "outline_color_rgba" , color_map[cSelectionRectOutline], + NULL); + + + rect->start_trim = gtk_canvas_item_new (GTK_CANVAS_GROUP(selection_group), + gtk_canvas_simplerect_get_type(), + "x1", (gdouble) 0.0, + "x2", (gdouble) 0.0, + "fill_color_rgba" , color_map[cSelectionStartFill], + "outline_color_rgba" , color_map[cSelectionStartOutline], + NULL); + + rect->end_trim = gtk_canvas_item_new (GTK_CANVAS_GROUP(selection_group), + gtk_canvas_simplerect_get_type(), + "x1", 0.0, + "x2", 0.0, + "fill_color_rgba" , color_map[cSelectionEndFill], + "outline_color_rgba" , color_map[cSelectionEndOutline], + NULL); + free_selection_rects.push_front (rect); + + gtk_signal_connect (GTK_OBJECT(rect->rect), "event", + (GtkSignalFunc) PublicEditor::canvas_selection_rect_event, + &editor); + gtk_signal_connect (GTK_OBJECT(rect->start_trim), "event", + (GtkSignalFunc) PublicEditor::canvas_selection_start_trim_event, + &editor); + gtk_signal_connect (GTK_OBJECT(rect->end_trim), "event", + (GtkSignalFunc) PublicEditor::canvas_selection_end_trim_event, + &editor); + + gtk_object_set_data(GTK_OBJECT(rect->rect), "rect", rect); + gtk_object_set_data(GTK_OBJECT(rect->start_trim), "rect", rect); + gtk_object_set_data(GTK_OBJECT(rect->end_trim), "rect", rect); + } + + rect = free_selection_rects.front(); + rect->id = id; + free_selection_rects.pop_front(); + return rect; +} + +bool +TimeAxisView::is_child (TimeAxisView* tav) +{ + return find (children.begin(), children.end(), tav) != children.end(); +} + +void +TimeAxisView::add_child (TimeAxisView* child) +{ + children.push_back (child); +} + +void +TimeAxisView::remove_child (TimeAxisView* child) +{ + vector::iterator i; + + if ((i = find (children.begin(), children.end(), child)) != children.end()) { + children.erase (i); + } +} + +void +TimeAxisView::get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list& result) +{ + return; +} + +void +TimeAxisView::get_inverted_selectables (Selection& sel, list& result) +{ + return; +} + +bool +TimeAxisView::touched (double top, double bot) +{ + /* remember: this is X Window - coordinate space starts in upper left and moves down. + y_position is the "origin" or "top" of the track. + */ + + double mybot = y_position + height; // XXX need to include Editor::track_spacing; + + return ((y_position <= bot && y_position >= top) || + ((mybot <= bot) && (top < mybot)) || + (mybot >= bot && y_position < top)); +} + +void +TimeAxisView::set_parent (TimeAxisView& p) +{ + parent = &p; +} + +bool +TimeAxisView::has_state () const +{ + return _has_state; +} + +TimeAxisView* +TimeAxisView::get_parent_with_state () +{ + if (parent == 0) { + return 0; + } + + if (parent->has_state()) { + return parent; + } + + return parent->get_parent_with_state (); +} + +void +TimeAxisView::set_state (const XMLNode& node) +{ + const XMLProperty *prop; + + if ((prop = node.property ("track_height")) != 0) { + + if (prop->value() == "largest") { + set_height (Largest); + } else if (prop->value() == "large") { + set_height (Large); + } else if (prop->value() == "larger") { + set_height (Larger); + } else if (prop->value() == "normal") { + set_height (Normal); + } else if (prop->value() == "smaller") { + set_height (Smaller); + } else if (prop->value() == "small") { + set_height (Small); + } else { + error << compose(_("unknown track height name \"%1\" in XML GUI information"), prop->value()) << endmsg; + set_height (Normal); + } + + } else { + set_height (Normal); + } +} + +void +TimeAxisView::reset_height() +{ + set_height ((TrackHeight) height); + + for (vector::iterator i = children.begin(); i != children.end(); ++i) { + (*i)->set_height ((TrackHeight)(*i)->height); + } +} + diff --git a/gtk2_ardour/time_axis_view.h b/gtk2_ardour/time_axis_view.h new file mode 100644 index 0000000000..a125e188ba --- /dev/null +++ b/gtk2_ardour/time_axis_view.h @@ -0,0 +1,290 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_time_axis_h__ +#define __ardour_gtk_time_axis_h__ + +#include +#include + +#include +#include + +#include +#include + +#include "prompter.h" +#include "axis_view.h" +#include "enums.h" +#include "editing.h" + +namespace ARDOUR { + class Session; + class Region; + class Session; + class RouteGroup; + class Playlist; +} + +class PublicEditor; +class AudioRegionSelection; +class TimeSelection; +class PointSelection; +class TimeAxisViewItem; +class Selection; +class Selectable; + +/** + * TimeAxisView defines the abstract base class for time-axis views. + * + * This class provides the basic LHS controls and display methods. This should be + * extended to create functional time-axis based views. + * + */ +class TimeAxisView : public virtual AxisView +{ + public: + enum TrackHeight { + /* canvas units. they need to be odd + valued so that there is a precise + middle. + */ + Largest = 301, + Large = 201, + Larger = 101, + Normal = 51, + Smaller = 31, + Small = 21 + }; + + TimeAxisView(ARDOUR::Session& sess, PublicEditor& ed, TimeAxisView* parent, Gtk::Widget *canvas); + virtual ~TimeAxisView (); + + /* public data: XXX create accessor/mutators for these ?? */ + + PublicEditor& editor; + + guint32 height; /* in canvas units */ + guint32 effective_height; /* in canvas units */ + double y_position; + int order; + + + GtkCanvasItem *canvas_display; + Gtk::VBox *control_parent; + + /* The Standard LHS Controls */ + Gtk::Frame controls_frame; + Gtk::HBox controls_hbox; + Gtk::EventBox controls_lhs_pad; + Gtk::Table controls_table; + Gtk::EventBox controls_ebox; + Gtk::VBox controls_vbox; + Gtk::HBox name_hbox; + Gtk::Frame name_frame; + Gtk::Entry name_entry; + + /** + * Display this TrackView as the nth component of the parent box, at y. + * + * @param y + * @param nth + * @param parent the parent component + * @return the height of this TrackView + */ + virtual guint32 show_at (double y, int& nth, Gtk::VBox *parent); + + bool touched (double top, double bot); + + /** + * Hides this TrackView + */ + virtual void hide (); + bool hidden() const { return _hidden; } + + virtual void set_selected (bool); + + /** + * potential handler for entered events + */ + + virtual void entered () {} + virtual void exited () {} + + /** + * Sets the height of this TrackView to one of ths TrackHeghts + * + * @param h the TrackHeight value to set + */ + virtual void set_height (TrackHeight h); + void reset_height(); + /** + * Steps through the defined TrackHeights for this TrackView. + * Sets bigger to true to step up in size, set to fals eot step smaller. + * + * @param bigger true if stepping should increase in size, false otherwise + */ + virtual void step_height (bool bigger); + + virtual ARDOUR::RouteGroup* edit_group() const { return 0; } + virtual ARDOUR::Playlist* playlist() const { return 0; } + + virtual void set_samples_per_unit (double); + virtual void show_selection (TimeSelection&); + virtual void hide_selection (); + virtual void reshow_selection (TimeSelection&); + virtual void show_timestretch (jack_nframes_t start, jack_nframes_t end); + virtual void hide_timestretch (); + + virtual void hide_dependent_views (TimeAxisViewItem&) {} + virtual void reveal_dependent_views (TimeAxisViewItem&) {} + + /* editing operations */ + + virtual bool cut_copy_clear (Selection&, Editing::CutCopyOp) { return false; } + virtual bool paste (jack_nframes_t, float times, Selection&, size_t nth) { return false; } + + virtual void set_selected_regionviews (AudioRegionSelection&) {} + virtual void set_selected_points (PointSelection&) {} + + virtual ARDOUR::Region* find_next_region (jack_nframes_t pos, ARDOUR::RegionPoint, int32_t dir) { + return 0; + } + + void order_selection_trims (GtkCanvasItem *item, bool put_start_on_top); + + virtual void get_selectables (jack_nframes_t start, jack_nframes_t end, double top, double bot, list& results); + virtual void get_inverted_selectables (Selection&, list& results); + + /* state/serialization management */ + + void set_parent (TimeAxisView& p); + bool has_state () const; + + virtual void set_state (const XMLNode&); + virtual XMLNode* get_state_node () { return 0; } + + /* call this on the parent */ + + virtual XMLNode* get_child_xml_node (std::string childname) { return 0; } + + protected: + + string controls_base_unselected_name; + string controls_base_selected_name; + + /** + * Handle mouse press on our LHS control name entry. + * + * @param ev the event + */ + virtual gint name_entry_button_press (GdkEventButton *ev); + + /** + * Handle mouse relaese on our LHS control name entry. + * + *@ param ev the event + */ + virtual gint name_entry_button_release (GdkEventButton *ev); + + /** + * Handle mouse relaese on our LHS control name ebox. + * + *@ param ev the event + */ + virtual gint controls_ebox_button_release (GdkEventButton *ev); + + /** + * Displays the standard LHS control menu at when. + * + * @param when the popup activation time + */ + virtual void popup_display_menu (guint32 when); + + /** + * Build the standard LHS control menu. + * Subclasses should extend this method to add their own menu options. + * + */ + virtual void build_display_menu (); + + /** + * Do anything that needs to be done to dynamically reset + * the LHS control menu. + */ + virtual gint handle_display_menu_map_event (GdkEventAny *ev) { return FALSE; } + + /** + * Build the standard LHS control size menu for the default TrackHeight options. + * + */ + virtual void build_size_menu(); + + /** + * Displays the standard LHS controls size menu for the TrackHeight. + * + * @parem when the popup activation time + */ + void popup_size_menu(guint32 when); + + /** + * Handle the size option of out main menu. + * + * @param ev the event + */ + gint size_click(GdkEventButton *ev); + + /* The standard LHS Track control popup-menus */ + + Gtk::Menu *display_menu; + Gtk::Menu *size_menu; + + Gtk::Label name_label; + + TimeAxisView* parent; + + /* find the parent with state */ + + TimeAxisView* get_parent_with_state(); + + std::vector children; + bool is_child (TimeAxisView*); + + void remove_child (TimeAxisView*); + void add_child (TimeAxisView*); + + /* selection display */ + + GtkCanvasItem *selection_group; + + list free_selection_rects; + list used_selection_rects; + + SelectionRect* get_selection_rect(uint32_t id); + + virtual void selection_click (GdkEventButton*); + + bool _hidden; + bool _has_state; + +}; /* class TimeAxisView */ + +#endif /* __ardour_gtk_time_axis_h__ */ + diff --git a/gtk2_ardour/time_axis_view_item.cc b/gtk2_ardour/time_axis_view_item.cc new file mode 100644 index 0000000000..9dffe8fcf6 --- /dev/null +++ b/gtk2_ardour/time_axis_view_item.cc @@ -0,0 +1,950 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include +#include + +#include "public_editor.h" +#include "time_axis_view_item.h" +#include "time_axis_view.h" +#include "canvas-simplerect.h" +#include "canvas-imageframe.h" +#include "utils.h" +#include "rgb_macros.h" + +#include "i18n.h" + +using namespace std; +using namespace Editing; + +//------------------------------------------------------------------------------ +/** Initialize static memeber data */ +std::string TimeAxisViewItem::NAME_FONT; +const double TimeAxisViewItem::NAME_X_OFFSET = 15.0; +const double TimeAxisViewItem::NAME_Y_OFFSET = 15.0 ; /* XXX depends a lot on the font size, sigh. */ +const double TimeAxisViewItem::NAME_HIGHLIGHT_SIZE = 15.0 ; /* ditto */ +const double TimeAxisViewItem::NAME_HIGHLIGHT_THRESH = 32.0 ; /* ditto */ +const double TimeAxisViewItem::GRAB_HANDLE_LENGTH = 6 ; + + +//---------------------------------------------------------------------------------------// +// Constructor / Desctructor + +/** + * Constructs a new TimeAxisViewItem. + * + * @param it_name the unique name/Id of this item + * @param parant the parent canvas group + * @param tv the TimeAxisView we are going to be added to + * @param spu samples per unit + * @param base_color + * @param start the start point of this item + * @param duration the duration of this item + */ +TimeAxisViewItem::TimeAxisViewItem(std::string it_name, GtkCanvasGroup* parent, TimeAxisView& tv, double spu, GdkColor& base_color, + jack_nframes_t start, jack_nframes_t duration, + Visibility visibility) + : trackview (tv) +{ + if (NAME_FONT.empty()) { + NAME_FONT = get_font_for_style (N_("TimeAxisViewItemName")); + } + + item_name = it_name ; + samples_per_unit = spu ; + should_show_selection = true; + frame_position = start ; + item_duration = duration ; + name_connected = false; + fill_opacity = 50; + position_locked = false ; + max_item_duration = ARDOUR::max_frames; + min_item_duration = 0 ; + show_vestigial = true; + + if (duration == 0) { + warning << "Time Axis Item Duration == 0" << endl ; + } + + group = gtk_canvas_item_new(GTK_CANVAS_GROUP(parent),gtk_canvas_group_get_type(),NULL) ; + + vestigial_frame = gtk_canvas_item_new(GTK_CANVAS_GROUP(group), + gtk_canvas_simplerect_get_type(), + "x1", (double) 0.0, + "y1", (double) 1.0, + "x2", 2.0, + "y2", (double) trackview.height, + "outline_color_rgba", color_map[cVestigialFrameOutline], + "fill_color_rgba", color_map[cVestigialFrameFill], + NULL); + gtk_canvas_item_hide (vestigial_frame); + + if (visibility & ShowFrame) { + frame = gtk_canvas_item_new(GTK_CANVAS_GROUP(group), + gtk_canvas_simplerect_get_type(), + "x1", (double) 0.0, + "y1", (double) 1.0, + "x2", (double) trackview.editor.frame_to_pixel(duration), + "y2", (double) trackview.height, + "outline_color_rgba", color_map[cTimeAxisFrameOutline], + "fill_color_rgba", color_map[cTimeAxisFrameFill], + NULL); + } else { + frame = 0; + } + + if (visibility & ShowNameHighlight) { + name_highlight = gtk_canvas_item_new(GTK_CANVAS_GROUP(group), + gtk_canvas_simplerect_get_type(), + "x1", (double) 1.0, + "x2", (double) (trackview.editor.frame_to_pixel(item_duration)) - 1, + "y1", (double) (trackview.height - TimeAxisViewItem::NAME_HIGHLIGHT_SIZE), + "y2", (double) (trackview.height - 1), + "outline_color_rgba", color_map[cNameHighlightFill], + "fill_color_rgba", color_map[cNameHighlightOutline], + NULL) ; + gtk_object_set_data(GTK_OBJECT(name_highlight), "timeaxisviewitem", this) ; + } else { + name_highlight = 0; + } + + if (visibility & ShowNameText) { + name_text = gtk_canvas_item_new(GTK_CANVAS_GROUP(group), + gtk_canvas_text_get_type(), + "x", (double) TimeAxisViewItem::NAME_X_OFFSET, + "y", (double) trackview.height + 1.0 - TimeAxisViewItem::NAME_Y_OFFSET, + "font", NAME_FONT.c_str(), + "anchor", GTK_ANCHOR_NW, + NULL) ; + gtk_object_set_data(GTK_OBJECT(name_text), "timeaxisviewitem", this) ; + + } else { + name_text = 0; + } + + /* create our grab handles used for trimming/duration etc */ + + if (visibility & ShowHandles) { + frame_handle_start = gtk_canvas_item_new(GTK_CANVAS_GROUP(group), + gtk_canvas_simplerect_get_type(), + "x1", (double) 0.0, + "x2", (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH, + "y1", (double) 1.0, + "y2", (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH+1, + "outline_color_rgba", color_map[cFrameHandleStartOutline], + "fill_color_rgba", color_map[cFrameHandleStartFill], + NULL) ; + + frame_handle_end = gtk_canvas_item_new(GTK_CANVAS_GROUP(group), + gtk_canvas_simplerect_get_type(), + "x1", (double) (trackview.editor.frame_to_pixel(get_duration())) - (TimeAxisViewItem::GRAB_HANDLE_LENGTH), + "x2", (double) trackview.editor.frame_to_pixel(get_duration()), + "y1", (double) 1, + "y2", (double) TimeAxisViewItem::GRAB_HANDLE_LENGTH + 1, + "outline_color_rgba", color_map[cFrameHandleEndOutline], + "fill_color_rgba", color_map[cFrameHandleEndFill], + NULL) ; + } else { + frame_handle_start = 0; + frame_handle_end = 0; + } + + set_color (base_color) ; + + set_duration (item_duration, this) ; + set_position (start, this) ; +} + + +/** + * Destructor + */ +TimeAxisViewItem::~TimeAxisViewItem() +{ + gtk_object_destroy (GTK_OBJECT(group)); +} + + +//---------------------------------------------------------------------------------------// +// Position and duration Accessors/Mutators + +/** + * Set the position of this item upon the timeline to the specified value + * + * @param pos the new position + * @param src the identity of the object that initiated the change + * @return true if the position change was a success, false otherwise + */ +bool +TimeAxisViewItem::set_position(jack_nframes_t pos, void* src, double* delta) +{ + if (position_locked) { + return false; + } + + frame_position = pos; + + /* This sucks. The GtkCanvas version I am using + doesn't correctly implement gtk_canvas_group_set_arg(), + so that simply setting the "x" arg of the group + fails to move the group. Instead, we have to + use gtk_canvas_item_move(), which does the right + thing. I see that in GNOME CVS, the current (Sept 2001) + version of GNOME Canvas rectifies this issue cleanly. + */ + + GtkArg args[1] ; + double old_unit_pos ; + double new_unit_pos = pos / samples_per_unit ; + + args[0].name = "x" ; + gtk_object_getv (GTK_OBJECT(group), 1, args) ; + old_unit_pos = GTK_VALUE_DOUBLE (args[0]) ; + + if (new_unit_pos != old_unit_pos) { + gtk_canvas_item_move (group, new_unit_pos - old_unit_pos, 0.0) ; + } + + if (delta) { + (*delta) = new_unit_pos - old_unit_pos; + } + + PositionChanged (frame_position, src) ; /* EMIT_SIGNAL */ + + return true; +} + +/** + * Return the position of this item upon the timeline + * + * @return the position of this item + */ +jack_nframes_t +TimeAxisViewItem::get_position() const +{ + return frame_position; +} + +/** + * Sets the duration of this item + * + * @param dur the new duration of this item + * @param src the identity of the object that initiated the change + * @return true if the duration change was succesful, false otherwise + */ +bool +TimeAxisViewItem::set_duration (jack_nframes_t dur, void* src) +{ + if ((dur > max_item_duration) || (dur < min_item_duration)) { + warning << compose (_("new duration %1 frames is out of bounds for %2"), get_item_name(), dur) + << endmsg; + return false; + } + + if (dur == 0) { + gtk_canvas_item_hide (group); + } + + item_duration = dur; + + double pixel_width = trackview.editor.frame_to_pixel (dur); + + reset_width_dependent_items (pixel_width); + + DurationChanged (dur, src) ; /* EMIT_SIGNAL */ + return true; +} + +/** + * Returns the duration of this item + * + */ +jack_nframes_t +TimeAxisViewItem::get_duration() const +{ + return (item_duration); +} + +/** + * Sets the maximum duration that this item make have. + * + * @param dur the new maximum duration + * @param src the identity of the object that initiated the change + */ +void +TimeAxisViewItem::set_max_duration(jack_nframes_t dur, void* src) +{ + max_item_duration = dur ; + MaxDurationChanged(max_item_duration, src) ; /* EMIT_SIGNAL */ +} + +/** + * Returns the maxmimum duration that this item may be set to + * + * @return the maximum duration that this item may be set to + */ +jack_nframes_t +TimeAxisViewItem::get_max_duration() const +{ + return(max_item_duration) ; +} + +/** + * Sets the minimu duration that this item may be set to + * + * @param the minimum duration that this item may be set to + * @param src the identity of the object that initiated the change + */ +void +TimeAxisViewItem::set_min_duration(jack_nframes_t dur, void* src) +{ + min_item_duration = dur ; + MinDurationChanged(max_item_duration, src) ; /* EMIT_SIGNAL */ +} + +/** + * Returns the minimum duration that this item mey be set to + * + * @return the nimum duration that this item mey be set to + */ +jack_nframes_t +TimeAxisViewItem::get_min_duration() const +{ + return(min_item_duration) ; +} + +/** + * Sets whether the position of this Item is locked to its current position + * Locked items cannot be moved until the item is unlocked again. + * + * @param yn set to true to lock this item to its current position + * @param src the identity of the object that initiated the change + */ +void +TimeAxisViewItem::set_position_locked(bool yn, void* src) +{ + position_locked = yn ; + set_trim_handle_colors() ; + PositionLockChanged (position_locked, src); /* EMIT_SIGNAL */ +} + +/** + * Returns whether this item is locked to its current position + * + * @return true if this item is locked to its current posotion + * false otherwise + */ +bool +TimeAxisViewItem::get_position_locked() const +{ + return (position_locked); +} + +/** + * Sets whether the Maximum Duration constraint is active and should be enforced + * + * @param active set true to enforce the max duration constraint + * @param src the identity of the object that initiated the change + */ +void +TimeAxisViewItem::set_max_duration_active(bool active, void* src) +{ + max_duration_active = active ; +} + +/** + * Returns whether the Maximum Duration constraint is active and should be enforced + * + * @return true if the maximum duration constraint is active, false otherwise + */ +bool +TimeAxisViewItem::get_max_duration_active() const +{ + return(max_duration_active) ; +} + +/** + * Sets whether the Minimum Duration constraint is active and should be enforced + * + * @param active set true to enforce the min duration constraint + * @param src the identity of the object that initiated the change + */ +void +TimeAxisViewItem::set_min_duration_active(bool active, void* src) +{ + min_duration_active = active ; +} + +/** + * Returns whether the Maximum Duration constraint is active and should be enforced + * + * @return true if the maximum duration constraint is active, false otherwise + */ +bool +TimeAxisViewItem::get_min_duration_active() const +{ + return(min_duration_active) ; +} + +//---------------------------------------------------------------------------------------// +// Name/Id Accessors/Mutators + +/** + * Set the name/Id of this item. + * + * @param new_name the new name of this item + * @param src the identity of the object that initiated the change + */ +void +TimeAxisViewItem::set_item_name(std::string new_name, void* src) +{ + if (new_name != item_name) { + std::string temp_name = item_name ; + item_name = new_name ; + NameChanged (item_name, temp_name, src) ; /* EMIT_SIGNAL */ + } +} + +/** + * Returns the name/id of this item + * + * @return the name/id of this item + */ +std::string +TimeAxisViewItem::get_item_name() const +{ + return(item_name) ; +} + +//---------------------------------------------------------------------------------------// +// Selection Methods + +/** + * Set to true to indicate that this item is currently selected + * + * @param yn true if this item is currently selected + * @param src the identity of the object that initiated the change + */ +void +TimeAxisViewItem::set_selected(bool yn, void* src) +{ + if (_selected != yn) { + _selected = yn ; + set_frame_color (); + Selected (_selected) ; /* EMIT_SIGNAL */ + } +} + +/** + * Returns whether this item is currently selected. + * + * @return true if this item is currently selected, false otherwise + */ +bool +TimeAxisViewItem::get_selected() const +{ + return (_selected) ; +} + +void +TimeAxisViewItem::set_should_show_selection (bool yn) +{ + if (should_show_selection != yn) { + should_show_selection = yn; + set_frame_color (); + } +} + +//---------------------------------------------------------------------------------------// +// Parent Componenet Methods + +/** + * Returns the TimeAxisView that this item is upon + * + * @return the timeAxisView that this item is placed upon + */ +TimeAxisView& +TimeAxisViewItem::get_time_axis_view() +{ + return trackview; +} +//---------------------------------------------------------------------------------------// +// ui methods & data + +/** + * Sets the displayed item text + * This item is the visual text name displayed on the canvas item, this can be different to the name of the item + * + * @param new_name the new name text to display + */ +void +TimeAxisViewItem::set_name_text(std::string new_name) +{ + if (name_text) { + gtk_canvas_item_set (name_text, "text", new_name.c_str(), NULL); + } +} + +/** + * Set the height of this item + * + * @param h the new height + */ +void +TimeAxisViewItem::set_height(double height) +{ + if (name_highlight) { + if (height < NAME_HIGHLIGHT_THRESH) { + gtk_canvas_item_hide (name_highlight); + gtk_canvas_item_hide (name_text); + } else { + gtk_canvas_item_show (name_highlight); + gtk_canvas_item_show (name_text); + } + + if (height > NAME_HIGHLIGHT_SIZE) { + gtk_canvas_item_set (name_highlight, + "y1", (double) height+1 - NAME_HIGHLIGHT_SIZE, + "y2", (double) height, + NULL); + } + else { + /* it gets hidden now anyway */ + gtk_canvas_item_set (name_highlight, + "y1", (double) 1.0, + "y2", (double) height, + NULL); + } + } + + if (name_text) { + gtk_canvas_item_set (name_text, "y", height+1 - NAME_Y_OFFSET, NULL); + if (height < NAME_HIGHLIGHT_THRESH) { + gtk_canvas_item_set(name_text, "fill_color_rgba", fill_color, NULL) ; + } + else { + gtk_canvas_item_set(name_text, "fill_color_rgba", label_color, NULL) ; + } + } + + if (frame) { + gtk_canvas_item_set (frame, "y2", height+1, NULL) ; + } + + gtk_canvas_item_set (vestigial_frame, "y2", height+1, NULL) ; +} + +/** + * + */ +void +TimeAxisViewItem::set_color(GdkColor& base_color) +{ + compute_colors (base_color); + set_colors (); +} + +/** + * + */ +GtkCanvasItem* +TimeAxisViewItem::get_canvas_frame() +{ + return(frame) ; +} + +/** + * + */ +GtkCanvasItem* +TimeAxisViewItem::get_canvas_group() +{ + return(group) ; +} + +/** + * + */ +GtkCanvasItem* +TimeAxisViewItem::get_name_highlight() +{ + return(name_highlight) ; +} + +/** + * + */ +GtkCanvasItem* +TimeAxisViewItem::get_name_text() +{ + return(name_text) ; +} + +/** + * Calculates some contrasting color for displaying various parts of this item, based upon the base color + * + * @param color the base color of the item + */ +void +TimeAxisViewItem::compute_colors(GdkColor& base_color) +{ + unsigned char radius ; + char minor_shift ; + + unsigned char r,g,b ; + + /* FILL: this is simple */ + r = base_color.red/256 ; + g = base_color.green/256 ; + b = base_color.blue/256 ; + fill_color = RGBA_TO_UINT(r,g,b,255) ; + + /* for minor colors: + if the overall saturation is strong, make the minor colors light. + if its weak, make them dark. + + we do this by moving an equal distance to the other side of the + central circle in the color wheel from where we started. + */ + + radius = (unsigned char) rint (floor (sqrt (static_cast(r*r + g*g + b+b))/3.0f)) ; + minor_shift = 125 - radius ; + + /* LABEL: rotate around color wheel by 120 degrees anti-clockwise */ + + r = base_color.red/256; + g = base_color.green/256; + b = base_color.blue/256; + + if (r > b) + { + if (r > g) + { + /* red sector => green */ + swap (r,g); + } + else + { + /* green sector => blue */ + swap (g,b); + } + } + else + { + if (b > g) + { + /* blue sector => red */ + swap (b,r); + } + else + { + /* green sector => blue */ + swap (g,b); + } + } + + r += minor_shift; + b += minor_shift; + g += minor_shift; + + label_color = RGBA_TO_UINT(r,g,b,255); + r = (base_color.red/256) + 127 ; + g = (base_color.green/256) + 127 ; + b = (base_color.blue/256) + 127 ; + + label_color = RGBA_TO_UINT(r,g,b,255); + + /* XXX can we do better than this ? */ + /* We're trying ;) */ + /* NUKECOLORS */ + + //frame_color_r = 192; + //frame_color_g = 192; + //frame_color_b = 194; + + //selected_frame_color_r = 182; + //selected_frame_color_g = 145; + //selected_frame_color_b = 168; + + //handle_color_r = 25 ; + //handle_color_g = 0 ; + //handle_color_b = 255 ; + //lock_handle_color_r = 235 ; + //lock_handle_color_g = 16; + //lock_handle_color_b = 16; +} + +/** + * Convenience method to set the various canvas item colors + */ +void +TimeAxisViewItem::set_colors() +{ + set_frame_color() ; + if (name_text) { + double height = NAME_HIGHLIGHT_THRESH; + + if (frame) { + GtkArg args[1] ; + args[0].name = "y2" ; + gtk_object_getv (GTK_OBJECT(frame), 1, args); + height = GTK_VALUE_DOUBLE (args[0]); + } + + if (height < NAME_HIGHLIGHT_THRESH) { + gtk_canvas_item_set(name_text, "fill_color_rgba", fill_color, NULL) ; + } + else { + gtk_canvas_item_set(name_text, "fill_color_rgba", label_color, NULL) ; + } + } + + if (name_highlight) { + gtk_canvas_item_set(name_highlight, "fill_color_rgba", fill_color, NULL) ; + gtk_canvas_item_set(name_highlight, "outline_color_rgba", fill_color, NULL) ; + } + set_trim_handle_colors() ; +} + +/** + * Sets the frame color depending on whether this item is selected + */ +void +TimeAxisViewItem::set_frame_color() +{ + if (frame) { + uint32_t r,g,b,a; + + if (_selected && should_show_selection) { + UINT_TO_RGBA(color_map[cSelectedFrameBase], &r, &g, &b, &a); + gtk_canvas_item_set(frame, "fill_color_rgba", RGBA_TO_UINT(r, g, b, fill_opacity), NULL) ; + } else { + UINT_TO_RGBA(color_map[cFrameBase], &r, &g, &b, &a); + gtk_canvas_item_set(frame, "fill_color_rgba", RGBA_TO_UINT(r, g, b, fill_opacity), NULL) ; + } + } +} + +/** + * Sets the colors of the start and end trim handle depending on object state + * + */ +void +TimeAxisViewItem::set_trim_handle_colors() +{ + if (frame_handle_start) { + if (position_locked) { + gtk_canvas_item_set(frame_handle_start, "fill_color_rgba", color_map[cTrimHandleLockedStart], NULL); + gtk_canvas_item_set(frame_handle_end, "fill_color_rgba", color_map[cTrimHandleLockedEnd], NULL) ; + } else { + gtk_canvas_item_set(frame_handle_start, "fill_color_rgba", color_map[cTrimHandleStart], NULL) ; + gtk_canvas_item_set(frame_handle_end, "fill_color_rgba", color_map[cTrimHandleEnd], NULL) ; + } + } +} + +double +TimeAxisViewItem::get_samples_per_unit() +{ + return(samples_per_unit) ; +} + +void +TimeAxisViewItem::set_samples_per_unit (double spu) +{ + samples_per_unit = spu ; + set_position (this->get_position(), this); + reset_width_dependent_items ((double)get_duration() / samples_per_unit); +} + +void +TimeAxisViewItem::reset_width_dependent_items (double pixel_width) +{ + if (pixel_width < GRAB_HANDLE_LENGTH * 2) { + + if (frame_handle_start) { + gtk_canvas_item_hide (frame_handle_start); + gtk_canvas_item_hide (frame_handle_end); + } + + } if (pixel_width < 2.0) { + + if (show_vestigial) { + gtk_canvas_item_show (vestigial_frame); + } + + if (name_highlight) { + gtk_canvas_item_hide (name_highlight); + gtk_canvas_item_hide (name_text); + } + + if (frame) { + gtk_canvas_item_hide (frame); + } + + if (frame_handle_start) { + gtk_canvas_item_hide (frame_handle_start); + gtk_canvas_item_hide (frame_handle_end); + } + + } else { + gtk_canvas_item_hide (vestigial_frame); + + if (name_highlight) { + + GtkArg args[1] ; + args[0].name = "y2" ; + gtk_object_getv (GTK_OBJECT(name_highlight), 1, args); + double height = GTK_VALUE_DOUBLE (args[0]); + + if (height < NAME_HIGHLIGHT_THRESH) { + gtk_canvas_item_hide (name_highlight); + gtk_canvas_item_hide (name_text); + } else { + gtk_canvas_item_show (name_highlight); + gtk_canvas_item_show (name_text); + reset_name_width (pixel_width); + } + + gtk_canvas_item_set (name_highlight, "x2", pixel_width - 1.0, NULL); + } + + if (frame) { + gtk_canvas_item_show (frame); + gtk_canvas_item_set (frame, "x2", pixel_width, NULL); + } + + if (frame_handle_start) { + if (pixel_width < (2*TimeAxisViewItem::GRAB_HANDLE_LENGTH)) { + gtk_canvas_item_hide (frame_handle_start); + gtk_canvas_item_hide (frame_handle_end); + } + gtk_canvas_item_show (frame_handle_start); + gtk_canvas_item_set(GTK_CANVAS_ITEM(frame_handle_end), "x1", pixel_width - (TimeAxisViewItem::GRAB_HANDLE_LENGTH ), NULL) ; + gtk_canvas_item_show (frame_handle_end); + gtk_canvas_item_set(GTK_CANVAS_ITEM(frame_handle_end), "x2", pixel_width, NULL) ; + } + } +} + +void +TimeAxisViewItem::reset_name_width (double pixel_width) +{ + gint width; + gint lbearing; + gint rbearing; + gint ascent; + gint descent; + Gdk_Font font (NAME_FONT); + + if (name_text == 0) { + return; + } + + int namelen = item_name.length(); + char cstr[namelen+1]; + strcpy (cstr, item_name.c_str()); + + while (namelen) { + + gdk_string_extents (font, + cstr, + &lbearing, + &rbearing, + &width, + &ascent, + &descent); + + if (width < (pixel_width - NAME_X_OFFSET)) { + break; + } + + --namelen; + cstr[namelen] = '\0'; + + } + + if (namelen == 0) { + + gtk_canvas_item_hide (name_text); + + } else { + + /* don't use name for event handling if it leaves no room + for trimming to work. + */ + + if (pixel_width - width < (NAME_X_OFFSET * 2.0)) { + if (name_connected) { + name_connected = false; + } + } else { + if (!name_connected) { + name_connected = true; + } + } + + gtk_canvas_item_set (name_text, "text", cstr, NULL); + gtk_canvas_item_show (name_text); + } +} + + +//---------------------------------------------------------------------------------------// +// Handle time axis removal + +/** + * Handles the Removal of this time axis item + * This _needs_ to be called to alert others of the removal properly, ie where the source + * of the removal came from. + * + * XXX Although im not too happy about this method of doing things, I cant think of a cleaner method + * just now to capture the source of the removal + * + * @param src the identity of the object that initiated the change + */ +void +TimeAxisViewItem::remove_this_item(void* src) +{ + /* + defer to idle loop, otherwise we'll delete this object + while we're still inside this function ... + */ + Gtk::Main::idle.connect(bind(slot(&TimeAxisViewItem::idle_remove_this_item), this, src)); +} + +/** + * Callback used to remove this time axis item during the gtk idle loop + * This is used to avoid deleting the obejct while inside the remove_this_item + * method + * + * @param item the ImageFrameTimeAxisGroup to remove + * @param src the identity of the object that initiated the change + */ +gint +TimeAxisViewItem::idle_remove_this_item(TimeAxisViewItem* item, void* src) +{ + item->ItemRemoved(item->get_item_name(), src) ; /* EMIT_SIGNAL */ + delete item ; + item = 0 ; + return(false) ; +} diff --git a/gtk2_ardour/time_axis_view_item.h b/gtk2_ardour/time_axis_view_item.h new file mode 100644 index 0000000000..a1eff29c4b --- /dev/null +++ b/gtk2_ardour/time_axis_view_item.h @@ -0,0 +1,453 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __gtk_ardour_time_axis_view_item_h__ +#define __gtk_ardour_time_axis_view_item_h__ + +#include +#include +#include +#include + +#include "selectable.h" + +class TimeAxisView; + +/** + * A base class for 'items' that may appear upon a TimeAxisView + * + */ +class TimeAxisViewItem : public SigC::Object, public Selectable +{ + public: + virtual ~TimeAxisViewItem() ; + + /** + * Set the position of this item upon the timeline to the specified value + * + * @param pos the new position + * @param src the identity of the object that initiated the change + * @return true if the position change was a success, false otherwise + */ + virtual bool set_position(jack_nframes_t pos, void* src, double* delta = 0) ; + + /** + * Return the position of this item upon the timeline + * + * @return the position of this item + */ + jack_nframes_t get_position() const ; + + /** + * Sets the duration of this item + * + * @param dur the new duration of this item + * @param src the identity of the object that initiated the change + * @return true if the duration change was succesful, false otherwise + */ + virtual bool set_duration(jack_nframes_t dur, void* src) ; + + /** + * Returns the duration of this item + * + */ + jack_nframes_t get_duration() const ; + + /** + * Sets the maximum duration that this item make have. + * + * @param dur the new maximum duration + * @param src the identity of the object that initiated the change + */ + virtual void set_max_duration(jack_nframes_t dur, void* src) ; + + /** + * Returns the maxmimum duration that this item may be set to + * + * @return the maximum duration that this item may be set to + */ + jack_nframes_t get_max_duration() const ; + + /** + * Sets the minimu duration that this item may be set to + * + * @param the minimum duration that this item may be set to + * @param src the identity of the object that initiated the change + */ + virtual void set_min_duration(jack_nframes_t dur, void* src) ; + + /** + * Returns the minimum duration that this item mey be set to + * + * @return the nimum duration that this item mey be set to + */ + jack_nframes_t get_min_duration() const ; + + /** + * Sets whether the position of this Item is locked to its current position + * Locked items cannot be moved until the item is unlocked again. + * + * @param yn set to true to lock this item to its current position + * @param src the identity of the object that initiated the change + */ + virtual void set_position_locked(bool yn, void* src) ; + + /** + * Returns whether this item is locked to its current position + * + * @return true if this item is locked to its current posotion + * false otherwise + */ + bool get_position_locked() const ; + + /** + * Sets whether the Maximum Duration constraint is active and should be enforced + * + * @param active set true to enforce the max duration constraint + * @param src the identity of the object that initiated the change + */ + void set_max_duration_active(bool active, void* src) ; + + /** + * Returns whether the Maximum Duration constraint is active and should be enforced + * + * @return true if the maximum duration constraint is active, false otherwise + */ + bool get_max_duration_active() const ; + + /** + * Sets whether the Minimum Duration constraint is active and should be enforced + * + * @param active set true to enforce the min duration constraint + * @param src the identity of the object that initiated the change + */ + void set_min_duration_active(bool active, void* src) ; + + /** + * Returns whether the Maximum Duration constraint is active and should be enforced + * + * @return true if the maximum duration constraint is active, false otherwise + */ + bool get_min_duration_active() const ; + + /** + * Set the name/Id of this item. + * + * @param new_name the new name of this item + * @param src the identity of the object that initiated the change + */ + void set_item_name(std::string new_name, void* src) ; + + /** + * Returns the name/id of this item + * + * @return the name/id of this item + */ + virtual std::string get_item_name() const ; + + /** + * Set to true to indicate that this item is currently selected + * + * @param yn true if this item is currently selected + * @param src the identity of the object that initiated the change + */ + virtual void set_selected(bool yn, void* src) ; + + /** + * Set to true to indicate that this item should show its selection status + * + * @param yn true if this item should show its selected status + */ + virtual void set_should_show_selection (bool yn) ; + + /** + * Returns whether this item is currently selected. + * + * @return true if this item is currently selected, false otherwise + */ + bool get_selected() const ; + + //---------------------------------------------------------------------------------------// + // Parent Component Methods + + /** + * Returns the TimeAxisView that this item is upon + * + * @return the timeAxisView that this item is placed upon + */ + TimeAxisView& get_time_axis_view() ; + + //---------------------------------------------------------------------------------------// + // ui methods & data + + /** + * Sets the displayed item text + * This item is the visual text name displayed on the canvas item, this can be different to the name of the item + * + * @param new_name the new name text to display + */ + void set_name_text(std::string new_name) ; + + /** + * Set the height of this item + * + * @param h the new height + */ + virtual void set_height(double h) ; + + /** + * + */ + void set_color(GdkColor& color) ; + + /** + * + */ + GtkCanvasItem* get_canvas_frame() ; + + /** + * + */ + GtkCanvasItem* get_canvas_group(); + + /** + * + */ + GtkCanvasItem* get_name_highlight(); + + /** + * + */ + GtkCanvasItem* get_name_text(); + + /** + * Sets the samples per unit of this item. + * this item is used to determine the relative visual size and position of this item + * based upon its duration and start value. + * + * @param spu the new samples per unit value + */ + virtual void set_samples_per_unit(double spu) ; + + /** + * Returns the current samples per unit of this item + * + * @return the samples per unit of this item + */ + double get_samples_per_unit() ; + + virtual void raise () { return; } + virtual void raise_to_top () { return; } + virtual void lower () { return; } + virtual void lower_to_bottom () { return; } + + /** + * returns true if the name area should respond to events. + */ + bool name_active() const { return name_connected; } + + // Default sizes, font and spacing + static std::string NAME_FONT ; + static const double NAME_X_OFFSET ; + static const double NAME_Y_OFFSET ; + static const double NAME_HIGHLIGHT_SIZE ; + static const double NAME_HIGHLIGHT_THRESH ; + static const double GRAB_HANDLE_LENGTH ; + + /** + * Handles the Removal of this time axis item + * This _needs_ to be called to alert others of the removal properly, ie where the source + * of the removal came from. + * + * XXX Although im not too happy about this method of doing things, I cant think of a cleaner method + * just now to capture the source of the removal + * + * @param src the identity of the object that initiated the change + */ + virtual void remove_this_item(void* src) ; + + /** + * Emitted when this Group has been removed + * This is different to the GoingAway signal in that this signal + * is emitted during the deletion of this Time Axis, and not during + * the destructor, this allows us to capture the source of the deletion + * event + */ + SigC::Signal2 ItemRemoved ; + + /** Emitted when the name/Id of this item is changed */ + SigC::Signal3 NameChanged ; + + /** Emiited when the position of this item changes */ + SigC::Signal2 PositionChanged ; + + /** Emitted when the position lock of this item is changed */ + SigC::Signal2 PositionLockChanged ; + + /** Emitted when the duration of this item changes */ + SigC::Signal2 DurationChanged ; + + /** Emitted when the maximum item duration is changed */ + SigC::Signal2 MaxDurationChanged ; + + /** Emitted when the mionimum item duration is changed */ + SigC::Signal2 MinDurationChanged ; + + /** Emitted when the selected status of this item changes */ + SigC::Signal1 Selected ; + + + protected: + + enum Visibility { + ShowFrame = 0x1, + ShowNameHighlight = 0x2, + ShowNameText = 0x4, + ShowHandles = 0x8 + }; + + /** + * Constructs a new TimeAxisViewItem. + * + * @param it_name the unique name/Id of this item + * @param parent the parent canvas group + * @param tv the TimeAxisView we are going to be added to + * @param spu samples per unit + * @param base_color + * @param start the start point of this item + * @param duration the duration of this item + */ + TimeAxisViewItem(std::string it_name, GtkCanvasGroup* parent, TimeAxisView& tv, double spu, GdkColor& base_color, + jack_nframes_t start, jack_nframes_t duration, Visibility v = Visibility (0)); + + /** + * Calculates some contrasting color for displaying various parts of this item, based upon the base color + * + * @param color the base color of the item + */ + virtual void compute_colors(GdkColor& color) ; + + /** + * convenience method to set the various canvas item colors + */ + virtual void set_colors() ; + + /** + * Sets the frame color depending on whether this item is selected + */ + void set_frame_color() ; + + /** + * Sets the colors of the start and end trim handle depending on object state + * + */ + void set_trim_handle_colors() ; + + virtual void reset_width_dependent_items (double pixel_width); + void reset_name_width (double pixel_width); + + /** + * Callback used to remove this item during the gtk idle loop + * This is used to avoid deleting the obejct while inside the remove_this_group + * method + * + * @param item the time axis item to remove + * @param src the identity of the object that initiated the change + */ + static gint idle_remove_this_item(TimeAxisViewItem* item, void* src) ; + + /** The time axis that this item is upon */ + TimeAxisView& trackview ; + + /** indicates whether this item is locked to its current position */ + bool position_locked ; + + /** The posotion of this item on the timeline */ + jack_nframes_t frame_position ; + + /** the duration of this item upon the timeline */ + jack_nframes_t item_duration ; + + /** the maximum duration that we allow this item to take */ + jack_nframes_t max_item_duration ; + + /** the minimu duration that we allow this item to take */ + jack_nframes_t min_item_duration ; + + /** indicates whether this Max Duration constraint is active */ + bool max_duration_active ; + + /** indicates whether this Min Duration constraint is active */ + bool min_duration_active ; + + /** the curretn samples per canvas unit */ + double samples_per_unit ; + + /** indicates if this item is currently selected */ + bool selected ; + + /** should the item show its selected status */ + bool should_show_selection; + + /** + * The unique item name of this Item + * Each item upon a time axis must have a unique id + */ + std::string item_name ; + + /** + * true if the name should respond to events + */ + bool name_connected; + + /** + * true if a small vestigial rect should be shown when the item gets very narrow + */ + + bool show_vestigial; + + uint32_t fill_opacity; + uint32_t fill_color ; + uint32_t frame_color_r ; + uint32_t frame_color_g ; + uint32_t frame_color_b ; + uint32_t selected_frame_color_r ; + uint32_t selected_frame_color_g ; + uint32_t selected_frame_color_b ; + uint32_t label_color ; + + uint32_t handle_color_r ; + uint32_t handle_color_g ; + uint32_t handle_color_b ; + uint32_t lock_handle_color_r ; + uint32_t lock_handle_color_g ; + uint32_t lock_handle_color_b ; + + GtkCanvasItem* group ; /* the group */ + GtkCanvasItem* vestigial_frame ; /* simplerect */ + GtkCanvasItem* frame ; /* simplerect */ + GtkCanvasItem* name_text ; /* text */ + GtkCanvasItem* name_highlight ; /* simplerect */ + GtkCanvasItem* frame_handle_start ; /* simplerect */ + GtkCanvasItem* frame_handle_end ; /* simplerect */ + +}; /* class TimeAxisViewItem */ + +#endif /* __gtk_ardour_time_axis_view_item_h__ */ diff --git a/gtk2_ardour/time_selection.cc b/gtk2_ardour/time_selection.cc new file mode 100644 index 0000000000..551e861176 --- /dev/null +++ b/gtk2_ardour/time_selection.cc @@ -0,0 +1,108 @@ +/* + Copyright (C) 2003-2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include + +#include +#include + +#include "time_selection.h" + +#include "i18n.h" + +using namespace ARDOUR; + +AudioRange& +TimeSelection::operator[] (uint32_t which) +{ + for (std::list::iterator i = begin(); i != end(); ++i) { + if ((*i).id == which) { + return *i; + } + } + fatal << compose (_("programming error: request for non-existent audio range (%1)!"), which) << endmsg; + /*NOTREACHED*/ + return *(new AudioRange(0,0,0)); /* keep the compiler happy; never called */ +} + +bool +TimeSelection::consolidate () +{ + bool changed = false; + + restart: + for (std::list::iterator a = begin(); a != end(); ++a) { + for (std::list::iterator b = begin(); b != end(); ++b) { + + if (&(*a) == &(*b)) { + continue; + } + + if ((*a).coverage ((*b).start, (*b).end) != OverlapNone) { + (*a).start = std::min ((*a).start, (*b).start); + (*a).end = std::max ((*a).end, (*b).end); + erase (b); + changed = true; + goto restart; + } + } + } + + return changed; +} + +jack_nframes_t +TimeSelection::start () +{ + if (empty()) { + return 0; + } + + jack_nframes_t first = max_frames; + + for (std::list::iterator i = begin(); i != end(); ++i) { + if ((*i).start < first) { + first = (*i).start; + } + } + return first; +} + +jack_nframes_t +TimeSelection::end_frame () +{ + jack_nframes_t last = 0; + + /* XXX make this work like RegionSelection: no linear search needed */ + + for (std::list::iterator i = begin(); i != end(); ++i) { + if ((*i).end > last) { + last = (*i).end; + } + } + return last; +} + +jack_nframes_t +TimeSelection::length() +{ + return end_frame() - start() + 1; +} + diff --git a/gtk2_ardour/time_selection.h b/gtk2_ardour/time_selection.h new file mode 100644 index 0000000000..f0db774733 --- /dev/null +++ b/gtk2_ardour/time_selection.h @@ -0,0 +1,38 @@ +#ifndef __ardour_gtk_time_selection_h__ +#define __ardour_gtk_time_selection_h__ + +#include +#include + +namespace ARDOUR { + class RouteGroup; +} + +class TimeAxisView; + +struct TimeSelection : public std::list { + + /* if (track == 0 && group == 0) then it applies to all + tracks. + + if (track != 0 && group == 0) then it applies just to + that track. + + if (group != 0) then it applies to all tracks in + the group. + */ + + TimeAxisView* track; + ARDOUR::RouteGroup* group; + + ARDOUR::AudioRange& operator[](uint32_t); + + jack_nframes_t start(); + jack_nframes_t end_frame(); + jack_nframes_t length(); + + bool consolidate (); +}; + + +#endif /* __ardour_gtk_time_selection_h__ */ diff --git a/gtk2_ardour/track_selection.h b/gtk2_ardour/track_selection.h new file mode 100644 index 0000000000..0c92ea40c2 --- /dev/null +++ b/gtk2_ardour/track_selection.h @@ -0,0 +1,10 @@ +#ifndef __ardour_gtk_track_selection_h__ +#define __ardour_gtk_track_selection_h__ + +#include + +class TimeAxisView; + +struct TrackSelection : public list {}; + +#endif /* __ardour_gtk_track_selection_h__ */ diff --git a/gtk2_ardour/transport_xpms b/gtk2_ardour/transport_xpms new file mode 100644 index 0000000000..a36071df92 --- /dev/null +++ b/gtk2_ardour/transport_xpms @@ -0,0 +1,181 @@ +/* XPM */ +static const gchar * loop_xpm[] = { +"19 19 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" ... ", +" .+.. ", +" .++.. ", +" ...+++.... ", +" ...++++++++... ", +" ..+++.+++..+++.. ", +" ..++...++.....++..", +" .++.. .+.. ..++.", +" .+.. ... ..+.", +" .+. .+.", +" .+.. ... ..+.", +" .++.. ..+. ..++.", +" ..++.....++...++..", +" ..+++..+++.+++.. ", +" ...++++++++... ", +" ....+++... ", +" ..++. ", +" ..+. ", +" ... "}; + +/* XPM */ +static const gchar * arrow_xpm[] = { +"19 19 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" ", +" ... ", +" .+.. ", +" .++.. ", +" .+++.. ", +" .++++.. ", +" .+++++.. ", +" .++++++.. ", +" .+++++++.. ", +" .++++++++. ", +" .+++++++.. ", +" .++++++.. ", +" .+++++.. ", +" .++++.. ", +" .+++.. ", +" .++.. ", +" .+.. ", +" ... ", +" "}; + +/* XPM */ +static const gchar * play_selection_xpm[] = { +"19 19 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" ", +".... ... ....", +".++. .+.. .++.", +".++. .++.. .++.", +".++. .+++.. .++.", +".++. .++++.. .++.", +".++. .+++++.. .++.", +".++. .++++++.. .++.", +".++...+++++++...++.", +".+++++++++++++++++.", +".++...+++++++...++.", +".++. .++++++.. .++.", +".++. .+++++.. .++.", +".++. .++++.. .++.", +".++. .+++.. .++.", +".++. .++.. .++.", +".++. .+.. .++.", +".... ... ....", +" "}; + +/* XPM */ +static const gchar * end_xpm[] = { +"19 19 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" ", +" ... ... ", +" .+.. .+.. ", +" .++.. .++. ", +" .+++.. .++. ", +" .++++.. .++. ", +" .+++++.. .++. ", +" .++++++...++. ", +" .+++++++..++. ", +" .+++++++..++. ", +" .+++++++..++. ", +" .++++++...++. ", +" .+++++.. .++. ", +" .++++.. .++. ", +" .+++.. .++. ", +" .++.. .++. ", +" .+.. .+.. ", +" ... ... ", +" "}; + +/* XPM */ +static const gchar * rec_xpm[] = { +"19 19 5 1", +" c None", +". c #FFFFFF", +"+ c #FDBEB6", +"@ c #F92104", +"# c #FB7A69", +" ", +" ", +" ..... ", +" .+@@@@@+. ", +" .@@@@@@@@#. ", +" .@@@@@@@@@@#. ", +" +@@@@@@@@@@@+ ", +" .@@@@@@@@@@@@@. ", +" .@@@@@@@@@@@@@. ", +" .@@@@@@@@@@@@@. ", +" .@@@@@@@@@@@@@. ", +" .@@@@@@@@@@@@@. ", +" +@@@@@@@@@@@+ ", +" .@@@@@@@@@@#. ", +" .@@@@@@@@#. ", +" .+@@@@@+. ", +" ..... ", +" ", +" "}; +/* XPM */ +static const gchar * start_xpm[] = { +"19 19 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" ", +" ... ... ", +" ..+. ..+. ", +" .++. ..++. ", +" .++. ..+++. ", +" .++. ..++++. ", +" .++. ..+++++. ", +" .++...++++++. ", +" .++..+++++++. ", +" .++..+++++++. ", +" .++..+++++++. ", +" .++...++++++. ", +" .++. ..+++++. ", +" .++. ..++++. ", +" .++. ..+++. ", +" .++. ..++. ", +" ..+. ..+. ", +" ... ... ", +" "}; +/* XPM */ +static const gchar * stop_xpm[] = { +"19 19 3 1", +" c None", +". c #000000", +"+ c #FFFFFF", +" ", +" ", +" ", +" ", +" ........... ", +" .+++++++++. ", +" .+++++++++. ", +" .+++++++++. ", +" .+++++++++. ", +" .+++++++++. ", +" .+++++++++. ", +" .+++++++++. ", +" .+++++++++. ", +" .+++++++++. ", +" ........... ", +" ", +" ", +" ", +" "}; diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc new file mode 100644 index 0000000000..4a023b8ad9 --- /dev/null +++ b/gtk2_ardour/utils.cc @@ -0,0 +1,520 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ardour_ui.h" +#include "utils.h" +#include "i18n.h" +#include "rgb_macros.h" + +using namespace std; +using namespace Gtk; + +string +short_version (string orig, string::size_type target_length) +{ + /* this tries to create a recognizable abbreviation + of "orig" by removing characters until we meet + a certain target length. + + note that we deliberately leave digits in the result + without modification. + */ + + + string::size_type pos; + + /* remove white-space and punctuation, starting at end */ + + while (orig.length() > target_length) { + if ((pos = orig.find_last_of (_("\"\n\t ,<.>/?:;'[{}]~`!@#$%^&*()_-+="))) == string::npos) { + break; + } + orig.replace (pos, 1, ""); + } + + /* remove lower-case vowels, starting at end */ + + while (orig.length() > target_length) { + if ((pos = orig.find_last_of (_("aeiou"))) == string::npos) { + break; + } + orig.replace (pos, 1, ""); + } + + /* remove upper-case vowels, starting at end */ + + while (orig.length() > target_length) { + if ((pos = orig.find_last_of (_("AEIOU"))) == string::npos) { + break; + } + orig.replace (pos, 1, ""); + } + + /* remove lower-case consonants, starting at end */ + + while (orig.length() > target_length) { + if ((pos = orig.find_last_of (_("bcdfghjklmnpqrtvwxyz"))) == string::npos) { + break; + } + orig.replace (pos, 1, ""); + } + + /* remove upper-case consonants, starting at end */ + + while (orig.length() > target_length) { + if ((pos = orig.find_last_of (_("BCDFGHJKLMNPQRTVWXYZ"))) == string::npos) { + break; + } + orig.replace (pos, 1, ""); + } + + /* whatever the length is now, use it */ + + return orig; +} + +string +fit_to_pixels (string str, int32_t pixel_width, Gdk_Font& font) +{ + gint width; + gint lbearing; + gint rbearing; + gint ascent; + gint descent; + + int namelen = str.length(); + char cstr[namelen+1]; + strcpy (cstr, str.c_str()); + + while (namelen) { + + gdk_string_extents (font, + cstr, + &lbearing, + &rbearing, + &width, + &ascent, + &descent); + + if (width < (pixel_width)) { + break; + } + + --namelen; + cstr[namelen] = '\0'; + + } + + return cstr; +} + +int +atoi (const string& s) +{ + return atoi (s.c_str()); +} + +double +atof (const string& s) +{ + return atof (s.c_str()); +} + +void +strip_whitespace_edges (string& str) +{ + string::size_type i; + string::size_type len; + string::size_type s; + + len = str.length(); + + for (i = 0; i < len; ++i) { + if (isgraph (str[i])) { + break; + } + } + + s = i; + + for (i = len - 1; i >= 0; --i) { + if (isgraph (str[i])) { + break; + } + } + + str = str.substr (s, (i - s) + 1); +} + +vector +internationalize (const char **array) +{ + vector v; + + for (uint32_t i = 0; array[i]; ++i) { + v.push_back (_(array[i])); + } + + return v; +} + +gint +just_hide_it (GdkEventAny *ev, Gtk::Window *win) +{ + ARDOUR_UI::instance()->allow_focus (false); + win->hide_all (); + return TRUE; +} + +void +allow_keyboard_focus (bool yn) +{ + ARDOUR_UI::instance()->allow_focus (yn); +} + +/* xpm2rgb copied from nixieclock, which bore the legend: + + nixieclock - a nixie desktop timepiece + Copyright (C) 2000 Greg Ercolano, erco@3dsite.com + + and was released under the GPL. +*/ + +unsigned char* +xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h) +{ + static long vals[256], val; + uint32_t t, x, y, colors, cpp; + unsigned char c; + unsigned char *savergb, *rgb; + + // PARSE HEADER + + if ( sscanf(xpm[0], "%u%u%u%u", &w, &h, &colors, &cpp) != 4 ) { + error << compose (_("bad XPM header %1"), xpm[0]) + << endmsg; + return 0; + } + + savergb = rgb = (unsigned char*)art_alloc (h * w * 3); + + // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION + for (t = 0; t < colors; ++t) { + sscanf (xpm[t+1], "%c c #%lx", &c, &val); + vals[c] = val; + } + + // COLORMAP -> RGB CONVERSION + // Get low 3 bytes from vals[] + // + + const char *p; + for (y = h-1; y > 0; --y) { + + for (p = xpm[1+colors+(h-y-1)], x = 0; x < w; x++, rgb += 3) { + val = vals[(int)*p++]; + *(rgb+2) = val & 0xff; val >>= 8; // 2:B + *(rgb+1) = val & 0xff; val >>= 8; // 1:G + *(rgb+0) = val & 0xff; // 0:R + } + } + + return (savergb); +} + +unsigned char* +xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h) +{ + static long vals[256], val; + uint32_t t, x, y, colors, cpp; + unsigned char c; + unsigned char *savergb, *rgb; + char transparent; + + // PARSE HEADER + + if ( sscanf(xpm[0], "%u%u%u%u", &w, &h, &colors, &cpp) != 4 ) { + error << compose (_("bad XPM header %1"), xpm[0]) + << endmsg; + return 0; + } + + savergb = rgb = (unsigned char*)art_alloc (h * w * 4); + + // LOAD XPM COLORMAP LONG ENOUGH TO DO CONVERSION + + if (strstr (xpm[1], "None")) { + sscanf (xpm[1], "%c", &transparent); + t = 1; + } else { + transparent = 0; + t = 0; + } + + for (; t < colors; ++t) { + sscanf (xpm[t+1], "%c c #%lx", &c, &val); + vals[c] = val; + } + + // COLORMAP -> RGB CONVERSION + // Get low 3 bytes from vals[] + // + + const char *p; + for (y = h-1; y > 0; --y) { + + char alpha; + + for (p = xpm[1+colors+(h-y-1)], x = 0; x < w; x++, rgb += 4) { + + if (transparent && (*p++ == transparent)) { + alpha = 0; + val = 0; + } else { + alpha = 255; + val = vals[(int)*p]; + } + + *(rgb+3) = alpha; // 3: alpha + *(rgb+2) = val & 0xff; val >>= 8; // 2:B + *(rgb+1) = val & 0xff; val >>= 8; // 1:G + *(rgb+0) = val & 0xff; // 0:R + } + } + + return (savergb); +} + +GtkCanvasPoints* +get_canvas_points (string who, uint32_t npoints) +{ + // cerr << who << ": wants " << npoints << " canvas points" << endl; +#ifdef TRAP_EXCESSIVE_POINT_REQUESTS + if (npoints > (uint32_t) gdk_screen_width() + 4) { + abort (); + } +#endif + return gtk_canvas_points_new (npoints); +} + +int +channel_combo_get_channel_count (Gtk::Combo& combo) +{ + string str = combo.get_entry()->get_text(); + int chns; + + if (str == _("mono")) { + return 1; + } else if (str == _("stereo")) { + return 2; + } else if ((chns = atoi (str)) != 0) { + return chns; + } else { + return 0; + } +} + +static int32_t +int_from_hex (char hic, char loc) +{ + int hi; /* hi byte */ + int lo; /* low byte */ + + hi = (int) hic; + + if( ('0'<=hi) && (hi<='9') ) { + hi -= '0'; + } else if( ('a'<= hi) && (hi<= 'f') ) { + hi -= ('a'-10); + } else if( ('A'<=hi) && (hi<='F') ) { + hi -= ('A'-10); + } + + lo = (int) loc; + + if( ('0'<=lo) && (lo<='9') ) { + lo -= '0'; + } else if( ('a'<=lo) && (lo<='f') ) { + lo -= ('a'-10); + } else if( ('A'<=lo) && (lo<='F') ) { + lo -= ('A'-10); + } + + return lo + (16 * hi); +} + +void +url_decode (string& url) +{ + string::iterator last; + string::iterator next; + + for (string::iterator i = url.begin(); i != url.end(); ++i) { + if ((*i) == '+') { + *i = ' '; + } + } + + if (url.length() <= 3) { + return; + } + + last = url.end(); + + --last; /* points at last char */ + --last; /* points at last char - 1 */ + + for (string::iterator i = url.begin(); i != last; ) { + + if (*i == '%') { + + next = i; + + url.erase (i); + + i = next; + ++next; + + if (isxdigit (*i) && isxdigit (*next)) { + /* replace first digit with char */ + *i = int_from_hex (*i,*next); + ++i; /* points at 2nd of 2 digits */ + url.erase (i); + } + } else { + ++i; + } + } +} + +string +get_font_for_style (string widgetname) +{ + Gtk::Label foobar; + + foobar.set_name (widgetname); + foobar.ensure_style(); + + if (foobar.get_style() == 0 || foobar.get_style()->gtkobj()->rc_style == 0 || foobar.get_style()->gtkobj()->rc_style->font_name == 0) { + return "fixed"; + } + + string str = foobar.get_style()->gtkobj()->rc_style->font_name; + + if (str.empty()) { + return "fixed"; // standard X Window fallback font + } else { + return str; + } +} +gint +pane_handler (GdkEventButton* ev, Gtk::Paned* pane) +{ + if (ev->window != Gtkmmext::get_paned_handle (*pane)) { + return FALSE; + } + + if (Keyboard::is_delete_event (ev)) { + + gint pos; + gint cmp; + + pos = Gtkmmext::gtk_paned_get_position (pane->gtkobj()); + + if (dynamic_cast(pane)) { + cmp = pane->height(); + } else { + cmp = pane->width(); + } + + /* we have to use approximations here because we can't predict the + exact position or sizes of the pane (themes, etc) + */ + + if (pos < 10 || abs (pos - cmp) < 10) { + + /* already collapsed: restore it (note that this is cast from a pointer value to int, which is tricky on 64bit */ + + pane->set_position ((gint64) pane->get_data ("rpos")); + + } else { + + int collapse_direction; + + /* store the current position */ + + pane->set_data ("rpos", (gpointer) pos); + + /* collapse to show the relevant child in full */ + + collapse_direction = (gint64) pane->get_data ("collapse-direction"); + + if (collapse_direction) { + pane->set_position (1); + } else { + if (dynamic_cast(pane)) { + pane->set_position (pane->height()); + } else { + pane->set_position (pane->width()); + } + } + } + + return TRUE; + } + + return FALSE; +} +uint32_t +rgba_from_style (string style, uint32_t r, uint32_t g, uint32_t b, uint32_t a) +{ + Gtk::Label foo; + + foo.set_name (style); + foo.ensure_style (); + + GtkRcStyle* waverc = foo.get_style()->gtkobj()->rc_style; + + if (waverc) { + r = waverc->fg[GTK_STATE_NORMAL].red / 257; + g = waverc->fg[GTK_STATE_NORMAL].green / 257; + b = waverc->fg[GTK_STATE_NORMAL].blue / 257; + + /* what a hack ... "a" is for "active" */ + + a = waverc->fg[GTK_STATE_ACTIVE].red / 257; + + } else { + warning << compose (_("missing RGBA style for \"%1\""), style) << endl; + } + + return (uint32_t) RGBA_TO_UINT(r,g,b,a); +} diff --git a/gtk2_ardour/utils.h b/gtk2_ardour/utils.h new file mode 100644 index 0000000000..bc0f5cfdec --- /dev/null +++ b/gtk2_ardour/utils.h @@ -0,0 +1,74 @@ +/* + Copyright (C) 2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_gtk_utils_h__ +#define __ardour_gtk_utils_h__ + +#include +#include +#include +#include +#include +#include + +namespace Gtk { + class Window; + class Combo; + class Paned; +} + +static inline double +gain_to_slider_position (ARDOUR::gain_t g) +{ + if (g == 0) return 0; + return pow((6.0*log(g)/log(2.0)+192.0)/198.0, 8.0); + +} + +static inline ARDOUR::gain_t +slider_position_to_gain (double pos) +{ + /* XXX Marcus writes: this doesn't seem right to me. but i don't have a better answer ... */ + if (pos == 0.0) return 0; + return pow (2.0,(sqrt(sqrt(sqrt(pos)))*198.0-192.0)/6.0); +} + +std::string short_version (std::string, std::string::size_type target_length); +std::string fit_to_pixels (std::string, int32_t pixel_width, Gdk_Font&); + +int atoi (const std::string&); +double atof (const std::string&); +void strip_whitespace_edges (std::string& str); +void url_decode (std::string&); +gint just_hide_it (GdkEventAny*, Gtk::Window*); +void allow_keyboard_focus (bool); + +unsigned char* xpm2rgb (const char** xpm, uint32_t& w, uint32_t& h); +unsigned char* xpm2rgba (const char** xpm, uint32_t& w, uint32_t& h); + +GtkCanvasPoints* get_canvas_points (std::string who, uint32_t npoints); + +int channel_combo_get_channel_count (Gtk::Combo& combo); +std::string get_font_for_style (std::string widgetname); + +gint pane_handler (GdkEventButton*, Gtk::Paned*); +uint32_t rgba_from_style (std::string style, uint32_t, uint32_t, uint32_t, uint32_t); + +#endif /* __ardour_gtk_utils_h__ */ diff --git a/gtk2_ardour/visual_time_axis.cc b/gtk2_ardour/visual_time_axis.cc new file mode 100644 index 0000000000..228a85b70b --- /dev/null +++ b/gtk2_ardour/visual_time_axis.cc @@ -0,0 +1,491 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ardour_ui.h" +#include "public_editor.h" +#include "imageframe_time_axis.h" +#include "canvas-simplerect.h" +#include "imageframe_time_axis_view.h" +#include "marker_time_axis_view.h" +#include "imageframe_view.h" +#include "marker_time_axis.h" +#include "marker_view.h" +#include "utils.h" +#include "prompter.h" +#include "rgb_macros.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace SigC; +using namespace Gtk; + +//XXX should really have a common home... +static const gchar* small_x_xpm[] = { + "11 11 2 1", + " c None", + ". c #000000", + " ", + " ", + " . . ", + " . . ", + " . . ", + " . ", + " . . ", + " . . ", + " . . ", + " ", + " "}; + + +/** + * Abstract Constructor for base visual time axis classes + * + * @param name the name/Id of thie TimeAxis + * @param ed the Ardour PublicEditor + * @param sess the current session + * @param canvas the parent canvas object + */ +VisualTimeAxis::VisualTimeAxis(std::string name, PublicEditor& ed, ARDOUR::Session& sess, Widget *canvas) + : AxisView(sess), + TimeAxisView(sess,ed,(TimeAxisView*) 0, canvas), + visual_button (_("v")), + size_button (_("h")) +{ + time_axis_name = name ; + name_prompter = 0 ; + _color = unique_random_color() ; + _marked_for_display = true; + + name_entry.activate.connect(slot(*this, &VisualTimeAxis::name_entry_changed)) ; + name_entry.focus_out_event.connect(slot(*this, &VisualTimeAxis::name_entry_focus_out_handler)) ; + name_entry.button_press_event.connect(slot(*this, &VisualTimeAxis::name_entry_button_press_handler)) ; + name_entry.button_release_event.connect(slot(*this, &VisualTimeAxis::name_entry_button_release_handler)) ; + name_entry.key_release_event.connect(slot(*this, &VisualTimeAxis::name_entry_key_release_handler)) ; + + size_button.set_name("TrackSizeButton") ; + visual_button.set_name("TrackVisualButton") ; + hide_button.set_name("TrackRemoveButton") ; + hide_button.add(*(Gtk::manage(new Gtk::Pixmap(small_x_xpm)))) ; + size_button.button_release_event.connect (slot (*this, &VisualTimeAxis::size_click)) ; + visual_button.clicked.connect (slot (*this, &VisualTimeAxis::visual_click)) ; + hide_button.clicked.connect (slot (*this, &VisualTimeAxis::hide_click)) ; + ARDOUR_UI::instance()->tooltips().set_tip(size_button,_("Display Height")) ; + ARDOUR_UI::instance()->tooltips().set_tip(visual_button, _("Visual options")) ; + ARDOUR_UI::instance()->tooltips().set_tip(hide_button, _("Hide this track")) ; + + controls_table.attach (hide_button, 0, 1, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + controls_table.attach (visual_button, 1, 2, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + controls_table.attach (size_button, 2, 3, 1, 2, GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND); + + /* remove focus from the buttons */ + size_button.unset_flags(GTK_CAN_FOCUS) ; + hide_button.unset_flags(GTK_CAN_FOCUS) ; + visual_button.unset_flags(GTK_CAN_FOCUS) ; + + set_height(Normal) ; +} + +/** + * VisualTimeAxis Destructor + * + */ +VisualTimeAxis::~VisualTimeAxis() +{ + if(name_prompter) + { + delete name_prompter ; + name_prompter = 0 ; + } +} + + +//---------------------------------------------------------------------------------------// +// Name/Id Accessors/Mutators + +void +VisualTimeAxis::set_time_axis_name(std::string name, void* src) +{ + std::string old_name = time_axis_name ; + + if(name != time_axis_name) + { + time_axis_name = name ; + label_view() ; + editor.route_name_changed(this) ; + + NameChanged(time_axis_name, old_name, src) ; /* EMIT_SIGNAL */ + } +} + +std::string +VisualTimeAxis::name() const +{ + return(time_axis_name) ; +} + + +//---------------------------------------------------------------------------------------// +// ui methods & data + +/** + * Sets the height of this TrackView to one of the defined TrackHeghts + * + * @param h the TrackHeight value to set + */ +void +VisualTimeAxis::set_height(TrackHeight h) +{ + TimeAxisView::set_height(h) ; + + switch (height) + { + case Largest: + case Large: + case Larger: + case Normal: + { + name_label.hide() ; + name_entry.show() ; + other_button_hbox.show_all() ; + break; + } + case Smaller: + { + name_label.hide() ; + name_entry.show() ; + other_button_hbox.hide_all() ; + break; + } + case Small: + { + name_label.show() ; + name_entry.hide() ; + other_button_hbox.hide_all() ; + } + break; + } +} + +/** + * Handle the visuals button click + * + */ +void +VisualTimeAxis::visual_click() +{ + popup_display_menu(0); +} + + +/** + * Handle the hide buttons click + * + */ +void +VisualTimeAxis::hide_click() +{ + editor.unselect_strip_in_display (*this); +} + + +/** + * Allows the selection of a new color for this TimeAxis + * + */ +void +VisualTimeAxis::select_track_color () +{ + if(choose_time_axis_color()) + { + //Does nothing at this abstract point + } +} + +/** + * Provides a color chooser for the selection of a new time axis color. + * + */ +bool +VisualTimeAxis::choose_time_axis_color() +{ + bool picked ; + GdkColor color ; + gdouble current[4] ; + + current[0] = _color.get_red() / 65535.0 ; + current[1] = _color.get_green() / 65535.0 ; + current[2] = _color.get_blue() / 65535.0 ; + current[3] = 1.0 ; + + color = Gtkmmext::UI::instance()->get_color(_("ardour: color selection"),picked, current) ; + + if (picked) + { + set_time_axis_color(color) ; + } + return(picked) ; +} + +/** + * Sets the color of this TimeAxis to the specified color c + * + * @param c the new TimeAxis color + */ +void +VisualTimeAxis::set_time_axis_color(Gdk_Color c) +{ + _color = c ; +} + +void +VisualTimeAxis::set_selected_regionviews (AudioRegionSelection& regions) +{ + // Not handled by purely visual TimeAxis +} + +//---------------------------------------------------------------------------------------// +// Handle time axis removal + +/** + * Handles the Removal of this VisualTimeAxis + * + * @param src the identity of the object that initiated the change + */ +void +VisualTimeAxis::remove_this_time_axis(void* src) +{ + vector choices; + + std::string prompt = compose (_("Do you really want to remove track \"%1\" ?\n(cannot be undone)"), time_axis_name); + + choices.push_back (_("Yes, remove it.")); + choices.push_back (_("No, do nothing.")); + + Gtkmmext::Choice prompter (prompt, choices); + + prompter.chosen.connect (Gtk::Main::quit.slot()); + prompter.show_all (); + + Gtk::Main::run (); + + if (prompter.get_choice() == 0) + { + /* + defer to idle loop, otherwise we'll delete this object + while we're still inside this function ... + */ + Gtk::Main::idle.connect(bind(slot(&VisualTimeAxis::idle_remove_this_time_axis), this, src)); + } +} + +/** + * Callback used to remove this time axis during the gtk idle loop + * This is used to avoid deleting the obejct while inside the remove_this_time_axis + * method + * + * @param ta the VisualTimeAxis to remove + * @param src the identity of the object that initiated the change + */ +gint +VisualTimeAxis::idle_remove_this_time_axis(VisualTimeAxis* ta, void* src) +{ + ta->VisualTimeAxisRemoved(ta->name(), src) ; /* EMIT_SIGNAL */ + delete ta ; + ta = 0 ; + return(false) ; +} + + + + +//---------------------------------------------------------------------------------------// +// Handle TimeAxis rename + +/** + * Construct a new prompt to receive a new name for this TimeAxis + * + * @see finish_time_axis_rename() + */ +void +VisualTimeAxis::start_time_axis_rename() +{ + if(name_prompter) + { + delete name_prompter ; + name_prompter = 0 ; + } + + name_prompter = new ArdourPrompter() ; + + name_prompter->set_prompt (_("new name: ")) ; + ARDOUR_UI::instance()->allow_focus(true) ; + name_prompter->done.connect (slot(*this, &VisualTimeAxis::finish_time_axis_rename)) ; + name_prompter->show_all() ; +} + +/** + * Handles the new name for this TimeAxis from the name prompt + * + * @see start_time_axis_rename() + */ +void +VisualTimeAxis::finish_time_axis_rename() +{ + name_prompter->hide_all () ; + ARDOUR_UI::instance()->allow_focus (false) ; + + if (name_prompter->status == Gtkmmext::Prompter::cancelled) + { + return; + } + + string result ; + name_prompter->get_result (result) ; + //time_axis_name = result ; + + if (editor.get_named_time_axis(result) != 0) { + ARDOUR_UI::instance()->popup_error (_("A track already exists with that name")); + return ; + } + + set_time_axis_name(result, this) ; + + delete name_prompter ; + name_prompter = 0 ; + label_view() ; +} + +/** + * Handle the (re-)displaying of the TimeAxis name label + * + */ +void +VisualTimeAxis::label_view() +{ + name_label.set_text(time_axis_name) ; + name_entry.set_text(time_axis_name) ; + ARDOUR_UI::instance()->tooltips().set_tip(name_entry, time_axis_name) ; +} + + +//---------------------------------------------------------------------------------------// +// Handle name entry signals + +void +VisualTimeAxis::name_entry_changed() +{ + ARDOUR_UI::generic_focus_out_event (0); + + string x = name_entry.get_text (); + + if (x == time_axis_name) { + return; + } + + if (x.length() == 0) { + name_entry.set_text (time_axis_name); + return; + } + + strip_whitespace_edges(x); + + if (!editor.get_named_time_axis(x)) { + set_time_axis_name(x, this); + } else { + ARDOUR_UI::instance()->popup_error (_("a track already exists with that name")); + name_entry.set_text(time_axis_name); + } +} + +gint +VisualTimeAxis::name_entry_button_press_handler(GdkEventButton *ev) +{ + if (ev->button == 3) { + return stop_signal (name_entry, "button_press_event"); + } + return FALSE; +} + +gint +VisualTimeAxis::name_entry_button_release_handler(GdkEventButton *ev) +{ + return FALSE; +} + +gint +VisualTimeAxis::name_entry_focus_out_handler(GdkEventFocus* ev) +{ + name_entry_changed(); + return TRUE; +} + +gint +VisualTimeAxis::name_entry_key_release_handler(GdkEventKey* ev) +{ + switch (ev->keyval) { + case GDK_Tab: + case GDK_Up: + case GDK_Down: + name_entry_changed (); + return TRUE; + + default: + return FALSE; + } +} + + +//---------------------------------------------------------------------------------------// +// Super class methods not handled by VisualTimeAxis + +void +VisualTimeAxis::show_timestretch (jack_nframes_t start, jack_nframes_t end) +{ + // Not handled by purely visual TimeAxis +} + +void +VisualTimeAxis::hide_timestretch() +{ + // Not handled by purely visual TimeAxis +} + + diff --git a/gtk2_ardour/visual_time_axis.h b/gtk2_ardour/visual_time_axis.h new file mode 100644 index 0000000000..6d9eb5cfb6 --- /dev/null +++ b/gtk2_ardour/visual_time_axis.h @@ -0,0 +1,277 @@ +/* + Copyright (C) 2003 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#ifndef __ardour_visual_time_axis_h__ +#define __ardour_visual_time_axis_h__ + +#include +#include +#include +#include + +#include "ardour_dialog.h" +#include "route_ui.h" +#include "enums.h" +#include "time_axis_view.h" + + +namespace ARDOUR +{ + class Session ; +} + +class PublicEditor; +class ImageFrameView; +class ImageFrameTimeAxisView; +class MarkersTimeAxisView; +class TimeSelection; +class AudioRegionSelection; +class MarkerTimeAxis; +class TimeAxisViewStrip; + +/** + * Base Abstact Class for TimeAxis views that operate purely within the visual domain. + * + * This class provides many of the common methods required for visual TimeAxis views. The aim is + * to provide an abstract layer during the developmnt of the visual based time axis'. Many of these + * methods have a better home further up the class heirarchy, and in fact some are replication of + * methods found within RouteUI. This, however, has been required due to various problems with previous + * versions of g++, mainly 2.95, which are not correctly handling virtual methods, virtual base classes, + * and virtual methods when used with Multiple Inheritance. Perhaps these could be combined once the + * compilers all agree on hos do to do stuff... + */ +class VisualTimeAxis : public TimeAxisView +{ + public: + //---------------------------------------------------------------------------------------// + // Constructor / Desctructor + + /** + * VisualTimeAxis Destructor + * + */ + virtual ~VisualTimeAxis() ; + + //---------------------------------------------------------------------------------------// + // Name/Id Accessors/Mutators + + /** + * Returns the name of this TimeAxis + * + * @return the name of this TimeAxis + */ + virtual std::string name() const ; + + /** + * Sets the name of this TimeAxis + * + * @param name the new name of this TimeAxis + * @param src the identity of the object that initiated the change + */ + virtual void set_time_axis_name(std::string name, void* src) ; + + + //---------------------------------------------------------------------------------------// + // ui methods & data + + /** + * Sets the height of this TrackView to one of the defined TrackHeghts + * + * @param h the TrackHeight value to set + */ + virtual void set_height (TrackHeight h); + + //---------------------------------------------------------------------------------------// + // Selection Methods + // selection methods are not handled by visual time axis object yet... + + /** + * Not implemented + */ + virtual void set_selected_regionviews(AudioRegionSelection&) ; + + + //---------------------------------------------------------------------------------// + // Emitted Signals + + /** + * Emitted when we have changed the gui, and what we have shanged + */ + SigC::Signal2 gui_changed ; + + /** + * Emitted when this Visual Time Axis has been removed + * This is different to the GoingAway signal in that this signal + * is emitted during the deletion of this Time Axis, and not during + * the destructor, this allows us to capture the source of the deletion + * event + */ + SigC::Signal2 VisualTimeAxisRemoved ; + + /** + * Emitted when we have changed the name of this TimeAxis + */ + SigC::Signal3 NameChanged ; + + /** + * Emitted when this time axis has been selected for removal + */ + //SigC::Signal2 VisualTimeAxisRemoved ; + + //---------------------------------------------------------------------------------------// + // Constructor / Desctructor + + /** + * Abstract Constructor for base visual time axis classes + * + * @param name the name/Id of thie TimeAxis + * @param ed the Ardour PublicEditor + * @param sess the current session + * @param canvas the parent canvas object + */ + VisualTimeAxis(std::string name, PublicEditor& ed, ARDOUR::Session& sess, Gtk::Widget* canvas) ; + + + //---------------------------------------------------------------------------------------// + // Handle time axis removal + + /** + * Handles the Removal of this VisualTimeAxis + * + * @param src the identity of the object that initiated the change + */ + virtual void remove_this_time_axis(void* src) ; + + /** + * Callback used to remove this time axis during the gtk idle loop + * This is used to avoid deleting the obejct while inside the remove_this_time_axis + * method + * + * @param ta the VisualTimeAxis to remove + * @param src the identity of the object that initiated the change + */ + static gint idle_remove_this_time_axis(VisualTimeAxis* ta, void* src) ; + + + + //---------------------------------------------------------------------------------------// + // ui methods & data + + /** + * Handle the visuals button click + * + */ + void visual_click() ; + + /** + * Handle the hide buttons click + * + */ + void hide_click() ; + + /** + * Allows the selection of a new color for this TimeAxis + * + */ + virtual void select_track_color() ; + + /** + * Provides a color chooser for the selection of a new time axis color. + * + */ + bool choose_time_axis_color() ; + + /** + * Sets the color of this TimeAxis to the specified color c + * + * @param c the new TimeAxis color + */ + void set_time_axis_color(Gdk_Color c) ; + + + //---------------------------------------------------------------------------------------// + // Handle TimeAxis rename + + /** + * Construct a new prompt to receive a new name for this TimeAxis + * + * @see finish_time_axis_rename() + */ + void start_time_axis_rename() ; + + /** + * Handles the new name for this TimeAxis from the name prompt + * + * @see start_time_axis_rename() + */ + void finish_time_axis_rename() ; + + /** + * Handle the (re-)displaying of the TimeAxis name label + * + */ + virtual void label_view() ; + + + //---------------------------------------------------------------------------------------// + // Handle name entry signals + + void name_entry_changed() ; + gint name_entry_focus_out_handler(GdkEventFocus*) ; + gint name_entry_key_release_handler(GdkEventKey*) ; + gint name_entry_button_release_handler(GdkEventButton*) ; + gint name_entry_button_press_handler(GdkEventButton*) ; + + //---------------------------------------------------------------------------------------// + // VisualTimeAxis Widgets + Gtk::HBox other_button_hbox ; + Gtk::Button hide_button ; + Gtk::Button visual_button ; + Gtk::Button size_button ; + + /** the name of this TimeAxis object */ + std::string time_axis_name ; + + /** used to get a new name for this TimeAxis */ + ArdourPrompter* name_prompter ; + + + //---------------------------------------------------------------------------------------// + // Super class methods not handled by VisualTimeAxis + + /** + * Not handled by purely Visual TimeAxis + * + * @todo should VisualTimeAxis handle this? + */ + void show_timestretch (jack_nframes_t start, jack_nframes_t end); + + /** + * Not handle by purely visual TimeAxis + * @see show_timestratch + */ + virtual void hide_timestretch() ; + + private: + +}; + +#endif /* __ardour_visual_time_axis_h__ */ + diff --git a/gtk2_ardour/vst_pluginui.cc b/gtk2_ardour/vst_pluginui.cc new file mode 100644 index 0000000000..bdb7ecded8 --- /dev/null +++ b/gtk2_ardour/vst_pluginui.cc @@ -0,0 +1,124 @@ +/* + Copyright (C) 2004 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include +#include +#include + +#include +#include + +#include "plugin_ui.h" +#include "prompter.h" + +#include "i18n.h" + +using namespace Gtk; +using namespace ARDOUR; + +VSTPluginUI::VSTPluginUI (PluginInsert& pi, VSTPlugin& vp) + : PlugUIBase (pi), + vst (vp) +{ + fst_run_editor (vst.fst()); + + preset_box.pack_end (bypass_button, false, false, 10); + preset_box.pack_end (save_button, false, false); + preset_box.pack_end (combo, false, false); + + bypass_button.set_active (!insert.active()); + + pack_start (preset_box, false, false); + pack_start (socket, true, true); +} + +VSTPluginUI::~VSTPluginUI () +{ + // nothing to do here - plugin destructor destroys the GUI +} + +int +VSTPluginUI::get_preferred_height () +{ + return vst.fst()->height; +} + +int +VSTPluginUI::package (Gtk::Window& win) +{ + /* for GTK+2, remove this: you cannot add to a realized socket */ + + socket.realize (); + + /* forward configure events to plugin window */ + + win.configure_event.connect (bind (slot (*this, &VSTPluginUI::configure_handler), socket.gtkobj())); + + /* XXX in GTK2, use add_id() instead of steal, although add_id() + assumes that the window's owner understands the XEmbed protocol. + */ + + socket.steal (fst_get_XID (vst.fst())); + + return 0; +} + +gboolean +VSTPluginUI::configure_handler (GdkEventConfigure* ev, GtkSocket *socket) +{ + XEvent event; + + gint x, y; + + if (socket->plug_window == NULL) { + return FALSE; + } + + event.xconfigure.type = ConfigureNotify; + event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window); + event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window); + + /* The ICCCM says that synthetic events should have root relative + * coordinates. We still aren't really ICCCM compliant, since + * we don't send events when the real toplevel is moved. + */ + gdk_error_trap_push (); + gdk_window_get_origin (socket->plug_window, &x, &y); + gdk_error_trap_pop (); + + event.xconfigure.x = x; + event.xconfigure.y = y; + event.xconfigure.width = GTK_WIDGET(socket)->allocation.width; + event.xconfigure.height = GTK_WIDGET(socket)->allocation.height; + + event.xconfigure.border_width = 0; + event.xconfigure.above = None; + event.xconfigure.override_redirect = False; + + gdk_error_trap_push (); + XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window), + GDK_WINDOW_XWINDOW (socket->plug_window), + False, StructureNotifyMask, &event); + // gdk_display_sync (GDK_WINDOW_XDISPLAY (socket->plug_window)); + gdk_error_trap_pop (); + + return FALSE; +} +