PageSourceSearch

https://samply.app/assets/index.0bc5305f.js

js samply.app collected 2026-09-24 17:52:26 UTC 19,004 bytes, 1 lines download raw bytes

1import{P as me}from"./PageLayout.34b004d4.js";import{_ as Z}from"./SectionHeader.vue_vue_type_script_setup_true_lang.96ef4a01.js";import{T as Q}from"./TransitionFade.b40c17b6.js";import{d as N,r as b,w as O,G as fe,o as h,g as x,b as k,p as y,a as F,c as j,H as pe,P as ye,e as U,h as ie,u as r,F as z,t as Y,aQ as ve,i as E,Q as ge,_ as ce,ab as ke,dY as he,a4 as we,a7 as _e,a8 as R,aa as X,a6 as ae,ea as be,el as xe,a5 as Ae,ae as Pe,m as Se,j as Ce,a2 as Te,aC as Ee,i0 as Ie,aD as De,a9 as Fe,aK as H,bt as ue,eh as We,$ as $e,au as Re,V as Le,x as je,dV as J,A as ze,y as Be,R as Me}from"./index.a7219c61.js";import{B}from"./BaseButton.070a6b6d.js";import{W as Ve}from"./Waveform.7fedaab3.js";import{u as Ue}from"./useDragAndDrop.2787f306.js";import{u as Ne}from"./useEasing.5d4efb84.js";import{_ as ee}from"./_plugin-vue_export-helper.cdc0426e.js";import{B as Oe}from"./BaseImage.b2704cd7.js";import{_ as Ye}from"./Icon.vue_vue_type_script_setup_true_lang.bd97c4b4.js";import{D as K}from"./Divider.1b862621.js";import{_ as qe}from"./Dropdown.vue_vue_type_script_setup_true_lang.5ca37045.js";import{I as He}from"./InsightsListItem.bfb03bfc.js";import{_ as Je}from"./ScrollSentinel.vue_vue_type_script_setup_true_lang.6d1da61b.js";import{u as Ge}from"./useInsightsFormatter.d68a9951.js";import{Y as Qe}from"./YouTube.8ac637b1.js";import{_ as ne}from"./Preference.vue_vue_type_script_setup_true_lang.638e50d3.js";import{I as Ke}from"./InputSwitch.a16649c7.js";import{u as Ze}from"./useSnapshot.470cd6d6.js";import"./useFilesStore.730bdd9d.js";import"./useBoxes.18a69a0a.js";import"./files.8f5c9851.js";import"./index.1ffd022d.js";import"./usePlayerUtil.82a36452.js";import"./useFileInput.ab6184fb.js";import"./useLayout.49d39e61.js";import"./useSharedDragAndDrop.af757c69.js";import"./useBreakpoint.a9cd55ed.js";import"./Wafer.0da5fda0.js";import"./TransitionExpand.vue_vue_type_script_setup_true_lang.13b0117c.js";import"./Avatar.d7b83e08.js";import"./GlslCanvas.es.3836f17a.js";/* empty css                                                                */import"./BaseInputSwitch.166bf8bd.js";/* empty css                                                                        *//* empty css                                                                    */const Xe={key:"empty",class:"empty-state d-flex flex-column align-center justify-center"},et={key:"waveform",class:"waveform-state"},tt={key:1,class:"s-body s-text-tertiary",textContent:"..."},at=N({__name:"WatermarkTracePanel",props:{file:{default:null},waveformPeaks:{default:()=>[]},analyzing:{type:Boolean,default:!1},showAnalyzeAnother:{type:Boolean,default:!1}},emits:["select","analyze-another"],setup(n,{emit:l}){const a=n,e=l,{lerp:t}=Ne(),s=b(null),u=b(0),i=b(0);let o=null,m=null;const{dragShield:_,onDropFromSystem:S}=Ue();S(f=>{const P=f.files?.[0];P&&e("select",P)});function w(){a.file||s.value?.click()}function p(f){const T=f.target.files?.[0];T&&e("select",T)}function d(){o!==null&&(cancelAnimationFrame(o),o=null)}function v(){m!==null&&(cancelAnimationFrame(m),m=null)}function A(){d(),u.value=0,a.analyzing&&(i.value=0,I(1));const f=performance.now(),P=1e3,T=W=>{const C=Math.min(1,(W-f)/P),c=C<.5?16*C**5:1-(-2*C+2)**5/2;u.value=t(0,1,c),C<1?o=requestAnimationFrame(T):(u.value=1,o=null)};o=requestAnimationFrame(T)}function I(f,P=250){v();const T=i.value;if(T===f)return;const W=performance.now(),C=c=>{const g=Math.min(1,(c-W)/P),D=g<.5?16*g**5:1-(-2*g+2)**5/2;i.value=t(T,f,D),g<1?m=requestAnimationFrame(C):(i.value=f,m=null)};m=requestAnimationFrame(C)}return O(()=>a.analyzing,f=>{I(f?1:0)}),O(()=>a.file,f=>{f||(d(),v(),u.value=0,i.value=0)}),O(()=>a.waveformPeaks?.length??0,f=>{f===0&&(d(),u.value=0)}),fe(()=>{d(),v()}),(f,P)=>(h(),x(z,null,[k("div",{class:ie(["trace-panel d-flex flex-column align-center justify-center s-bg-surface-light s-rounded-4",{"is-empty":!f.file,"highlight-dropzone":!f.file&&r(_),"s-outlined":!!f.file}]),onClick:w},[y(Q,null,{default:F(()=>[f.file?(h(),x("div",et,[f.waveformPeaks.length?(h(),j(Ve,{key:0,class:"waveform-fill",waveform:f.waveformPeaks,"show-playhead":!1,height:u.value,"scan-effect":i.value,onReady:A},null,8,["waveform","height","scan-effect"])):(h(),x("span",tt)),y(pe,{name:"analyze-another-fade"},{default:F(()=>[f.showAnalyzeAnother?(h(),j(B,{key:0,class:"analyze-another",label:"Analyze another track",icon:"mdi-fingerprint",onClick:P[0]||(P[0]=ye(T=>f.$emit("analyze-another"),["stop"]))})):U("",!0)]),_:1}
1)])):(h(),x("div",Xe,[y(B,{class:"mb-3",label:"Choose audio",icon:"mdi-plus",variant:"primary"}),P[1]||(P[1]=k("span",{class:"s-body s-text-tertiary hidden-mobile"}," or drag and drop ",-1))]))]),_:1})],2),k("input",{ref_key:"fileInput",ref:s,type:"file",class:"file-input",onChange:p},null,544)],64))}});const nt=ee(at,[["__scopeId","data-v-40e8f518"]]),rt={class:"d-flex align-center s-bg-surface-light s-outlined s-rounded-4 pa-3 gap-3 mt-4"},ot={class:"redacted-artwork d-flex align-center justify-center"},st={class:"d-flex flex-column flex-grow-1"},lt={class:"s-body-semi-bold s-text-primary"},it={class:"s-caption s-text-secondary"},ct=N({__name:"WatermarkResultCard",props:{redacted:{type:Boolean},title:{},subtitle:{},artwork:{}},emits:["open"],setup(n,{emit:l}){const a=l;return(e,t)=>e.redacted?(h(),x(z,{key:0},[k("div",rt,[k("div",ot,[y(Ye,{icon:"mdi-lock",size:18,color:"var(--s-text-tertiary)"})]),t[1]||(t[1]=k("div",{class:"d-flex flex-column flex-grow-1 gap-2"},[k("span",{class:"redacted-bar redacted-bar--title"}),k("span",{class:"redacted-bar redacted-bar--subtitle"})],-1))]),t[2]||(t[2]=k("p",{class:"s-caption s-text-secondary text-center mt-4"}," This asset matches a watermarked link that you don't have access to. Contact us for more information. ",-1))],64)):(h(),x("div",{key:1,class:"d-flex align-center s-bg-surface-light s-outlined s-rounded-4 pa-3 gap-3 mt-4",style:{cursor:"pointer"},onClick:t[0]||(t[0]=s=>a("open"))},[y(Oe,{"image-set":e.artwork,"max-variant":"small",width:44,height:44,rounded:""},null,8,["image-set"]),k("div",st,[k("span",lt,Y(e.title),1),k("span",it,Y(e.subtitle),1)]),y(B,{label:"Go to project",icon:"mdi-arrow-right"})]))}});const ut=ee(ct,[["__scopeId","data-v-5d382091"]]),re=25,dt=["play","export","share","first-open"];function mt(n={}){const l=ce(),{delineateByDay:a}=Ge(),e=b("all"),t=b([]),s=b(!1),u=b(!1);let i,o,m;function _(c){return c&&typeof c.toDate=="function"?c.toDate():new Date(0)}function S(c,g){return c||`Someone from ${g?.city??"unknown"}`}function w(c){const g={play:"played",export:"exported",share:"shared",open:"opened","first-open":"opened"}[c.type]??c.type,D=c.time.toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit"});return`${S(c.creator?.displayName,c.ipInfo)} ${g} \xB7 ${D}`}function p(c){switch(c){case"play":return"play-with-completion";case"export":return"mdi-arrow-collapse-down";case"share":return"mdi-link-variant";case"first-open":return"mdi-eye-outline";default:return}}function d(c){if(!m)throw new Error("no activity target set");const g=e.value==="all"?dt:[e.value];return we(_e(X(),R.PROJECTS,m.projectid,R.ACTIVITY),ae("playerid","==",m.playerid),ae("type","in",g),be("timeCreated","desc"),...c?[xe(c)]:[],Ae(re))}function v(c){const g=c.data();return{viewModelType:"activity",key:c.id,id:c.id,type:g.type,creator:g.creator,label:g.resourceName||n.fallbackLabel?.()||"?",time:_(g.timeCreated),completion:Math.min(1,g.completion??0),ipInfo:g.ipInfo}}function A(){t.value.sort((c,g)=>g.time.getTime()-c.time.getTime())}function I(){i&&(i(),i=void 0)}function f(c,g){I(),m={projectid:c,playerid:g},t.value=[],u.value=!1,o=void 0,s.value=!0,i=ke(d(),D=>
1{D.docChanges().forEach($=>{if($.type==="added")t.value.some(M=>M.id===$.doc.id)||t.value.push(v($.doc));else if($.type==="modified"){const M=t.value.findIndex(de=>de.id===$.doc.id);M!==-1&&(t.value[M]=v($.doc))}else $.type==="removed"&&(t.value=t.value.filter(M=>M.id!==$.doc.id))}),A();const q=D.docs[D.docs.length-1];q&&(o=q),s.value=!1})}async function P(){if(!(!m||u.value||s.value||!o)){s.value=!0;try{const c=await he(d(o));c.docs.forEach(D=>{t.value.some(q=>q.id===D.id)||t.value.push(v(D))}),A();const g=c.docs[c.docs.length-1];g&&(o=g),c.docs.length<re&&(u.value=!0)}catch(c){console.error("[watermarking] failed to load more activity",c)}finally{s.value=!1}}}O(e,()=>{m&&f(m.projectid,m.playerid)}),ve(I);const T=E(()=>a(t.value,{getDate:c=>c.time,formatDate:c=>l.timestampToString(c)})),W=E(()=>({all:"All",play:"Plays",export:"Exports",share:"Shares"})[e.value]),C=E(()=>[{name:"all",label:"All",action:()=>{}},ge(),{name:"play",label:"Plays",action:()=>{}},{name:"export",label:"Exports",action:()=>{}},{name:"share",label:"Shares",action:()=>{}}]);return{activityFilter:e,activityItems:T,activityLoading:s,activityAllLoaded:u,activityFilterLabel:W,activityFilterCommands:C,activityActionString:w,activityIcon:p,startActivityFeed:f,loadMoreActivity:P}}const ft={class:"d-flex flex-column gap-6"},pt={key:0,class:"s-body s-text-tertiary"},yt=N({__name:"WatermarkActivityFeed",props:{projectid:{},playerid:{},fallbackLabel:{}},setup(n){const l=n,{activityFilter:a,activityItems:e,activityLoading:t,activityAllLoaded:s,activityFilterLabel:u,activityFilterCommands:i,activityActionString:o,activityIcon:m,startActivityFeed:_,loadMoreActivity:S}=mt({fallbackLabel:()=>l.fallbackLabel??""});return O(()=>[l.projectid,l.playerid],([w,p])=>{w&&p&&_(w,p)},{immediate:!0}),(w,p)=>(h(),x(z,null,[y(Z,{title:"Activity",size:"sm",class:"mt-8 mb-6"},{default:F(()=>[y(r(qe),{modelValue:r(a),"onUpdate:modelValue":p[0]||(p[0]=d=>Pe(a)?a.value=d:null),select:"",commands:r(i),"aria-label":"Activity filter",style:{"margin-right":"-12px"}},{activator:F(({attrs:d})=>[y(B,Se(d,{label:r(u),variant:"text",icon:"mdi-chevron-down","icon-trailing":""}),null,16,["label"])]),_:1},8,["modelValue","commands"])]),_:1}),k("div",ft,[(h(!0),x(z,null,Ce(r(e),d=>(h(),x(z,{key:d.key},[d.viewModelType==="day-divider"?(h(),j(K,{key:0,label:d.dateString},null,8,["label"])):d.viewModelType==="activity"?(h(),j(He,{key:1,label:d.label,"top-context":r(o)(d),"ip-info":d.ipInfo,icon:r(m)(d.type),completion:d.completion},null,8,["label","top-context","ip-info","icon","completion"])):U("",!0)],64))),128)),!r(e).length&&!r(t)?(h(),x("p",pt," No activity yet ")):U("",!0),y(Je,{"all-loaded":r(s),onIntersecting:r(S)},null,8,["all-loaded","onIntersecting"])])],64))}});function te(){const n=De({}),l=Te(),a=Ee();function e(){const s=n.check("preferences-watermarking");return s.fail&&s.failedChecks.includes(Ie.Plan)?(l.showUpgradeDialog("preferences-watermarking"),!1):!0}return{watermarkingEnabled:E({get:()=>a.getWatermarking,set:s=>{s&&!e()||a.setWatermarking(s)}}),checkAndPrompt:e}}const vt={class:"d-flex align-center justify-space-between s-bg-surface-regular s-rounded-lg s-outlined px-4 py-4 mb-6"},gt=N({__name:"WatermarkingSplash",setup(n){const{watermarkingEnabled:l}=te();return(a,e)=>(h(),x("div",null,[e[2]||(e[2]=k("p",{class:"s-body s-text-secondary mb-6"}," Tag audio with an inaudible fingerprint. If a track leaks, trace it back to the link it came from. ",-1)),k("div",vt,[e[1]||(e[1]=k("div",{class:"d-flex flex-column gap-1"},[k("h3",{class:"s-body"},"Watermarking is off"),k("h5",{class:"s-caption s-text-secondary"}," Turning this on adds a watermark switch to your link settings and unlocks leak tracing. Existing links are unaffected. ")],-1)),y(B,{onClick:e[0]||(e[0]=t=>l.value=!0),label:"Turn on",variant:"primary",class:"flex-shrink-0"})]),y(Qe,{youtubeId:"myIJfZusujU?si=2Y1o-113BUxlM6zH"})]))}}),kt={class:"d-flex flex-column gap-4 pa-4 s-rounded-md s-outlined s-bg-lighten"},ht=N({__name:"WatermarkingPreferences",setup(n){const{watermarkingEnabled:l}=te(),a=Fe().currentUser?.uid,e=H(X(),R.USERS,a??"",R.PREFERENCES,ue.PLAYERS),{data:t}=Ze(e),s=E({get:()=>t.value?.config?.watermark??!1,set:u=>{We(e,{config:{watermark:u}},{merge:!0})}});return(u,i)=>(h(),x(z,null,[y(Z,{title:"Preferences",class:"mb-6 mt-8"}),k("div",kt,[y(Ke,{label:"Enable by default",details:"New links start with watermarking turned on",modelValue:s.value,"onUpdate:modelValue":i[0]||(i[0]=o=>s.value=o)},null,8,["modelValue"]),y(K),y(ne,{label:"Learn more",details:"How watermarking works and how to use it"},{default:F(()=>[y(B,{class:"flex-shrink-0",label:"Open docs",icon:"mdi-arrow-top-right","icon-trailing":"",href:"https://docs.samply.app/watermarking.html",openInNewTab:""})]),_:1}),y(K),y(ne,{label:"Watermarking is on",details:"Turning this off removes the watermark switch from your link settings and disables leak tracing. Existing links stay unchanged."},{default:F(()=>[y(B,{class:"flex-shrink-0",label:"Turn off",onClick:i[1]||(i[1]=o=>l.value=!1)})]),_:1})])],64))}});function wt(){return new Worker("/assets/peaks.worker.8ce6b3ea.js")}function oe(n,l){const a=n[0]?.length??0;if(a===0||l<=0)return[];const e=Math.max(1,Math.floor(a/l)),t=[];for(let s=0;s<l;s++){const u=s*e,i=s===l-1?a:Math.min(u+e,a);let o=0;for(const m of n)for(let _=u;_<i;_++){const S=Math.abs(m[_]);S>o&&(o=S)}t.push(o)}return t}const _t=44100,bt=8e3,xt=1e4,se=new Map;function At(n){let l=se.get(n);if(!l){const a=window.OfflineAudioContext||window.webkitOfflineAudioContext;l=new a(1,1,n),se.set(n,l)}return l}let L,G=!1,Pt=0;const V=new Map;function St(){if(L||G)return L;try{L=new wt,L.onmessage=n=>{const{id:l,peaks:a}=n.data,e=V.get(l);e&&(V.delete(l),e.resolve(a))},L.onerror=()=>{G=!0;for(const{reject:n}of V.values())n(new Error("Peaks worker failed"));V.clear(),L=void 0}}catch{G=!0}return L}function Ct(n,l){const a=St();return a?new Promise((e,t)=>
1{const s=Pt++;V.set(s,{resolve:e,reject:t});const u={id:s,channels:n,buckets:l},i=[...new Set(n.map(o=>o.buffer))];try{a.postMessage(u,i)}catch{V.delete(s),e(oe(n,l))}}):Promise.resolve(oe(n,l))}function Tt(){const n=b(!1),l=b(null);async function a(t,s={}){const u=s.sampleRate??_t;n.value=!0,l.value=null;try{const i=await t.arrayBuffer(),o=await At(u).decodeAudioData(i),m=[];for(let _=0;_<o.numberOfChannels;_++)m.push(o.getChannelData(_));return{channelData:m,sampleRate:o.sampleRate,duration:o.duration,length:o.length,numberOfChannels:o.numberOfChannels}}catch(i){const o=i instanceof Error?i:new Error("Failed to decode audio");throw l.value=o,o}finally{n.value=!1}}async function e(t,s={}){const{channelData:u}=await a(t,{sampleRate:s.sampleRate??bt});return Ct(u,s.buckets??xt)}return{decodeFile:a,getWaveformPeaks:e,decoding:n,error:l}}function Et(n={}){const l=$e(),a=Tt(),e=b(null),t=b("empty"),s=b([]),u=b(null),i=b(null),o=b(null),m=b(0),_=E(()=>{switch(t.value){case"empty":return"No file selected";case"uploading":return`uploading ${m.value}%...`;case"detecting":return"analyzing...";case"completed":return u.value?"Watermark detected":"null";case"error":return i.value??"An error occurred";default:return""}}),S=E(()=>t.value==="completed"&&!!u.value&&!o.value);async function w(d){if(!(d&&n.canProceed&&!n.canProceed())){if(e.value=d,u.value=null,o.value=null,i.value=null,s.value=[],m.value=0,n.onReset?.(),!d){t.value="empty";return}a.getWaveformPeaks(d).then(v=>{s.value=v}).catch(v=>{console.error("[watermarking] failed to decode audio",v)});try{t.value="uploading";const v=await l.uploadFileForWatermarkCheck(d,{onProgress:I=>{m.value=I}});t.value="detecting";const A=await Re().detectWatermark(v);u.value=A.detected,o.value=A.playerid??null,i.value=A.message??null,u.value&&o.value&&await n.onDetected?.(o.value),t.value="completed"}catch(v){console.error("Watermark detection failed",v),t.value="error",Le().show("Watermark detection failed",{details:v.message??"An unknown error occurred",variant:"error"})}}}function p(){w(null)}return{file:e,status:t,waveformPeaks:s,detected:u,message:i,playerid:o,statusMessage:_,isRedacted:S,setFile:w,reset:p}}function le(n){return Boolean(n&&(n.original?.src||n.large?.src||n.medium?.src||n.small?.src||n.micro?.src))}function It(){const n=je(),l=ze().artwork,a=b(),e=b(),t=E(()=>a.value?.name||e.value?.name||""),s=E(()=>e.value?.artist?.displayName||e.value?.creator?.displayName||a.value?.creator?.displayName||""),u=E(()=>a.value?.projectid??null),i=E(()=>u.value?Be().getShareId(u.value):void 0),o=E(()=>{const w=a.value?.artwork;if(le(w))return w;const p=e.value?.artwork;return le(p)?p:l});function m(){!i.value||n.push({name:"player",params:{shareid:i.value}})}async function _(w){const p=X();try{const d=await J(H(p,R.PLAYERS,w));a.value=d.data();const v=a.value?.projectid;if(!v)return null;try{const A=await J(H(p,R.PROJECTS,v));if(!A.exists())throw new Error("project doc unavailable");e.value=A.data()}catch{const A=await J(H(p,R.PROJECTS,v,R.PUBLIC,ue.SNIPPET));e.value=A.data()}return v}catch(d){return console.error("[watermarking] failed to load detected player",d),null}}function S(){a.value=void 0,e.value=void 0}return{playerData:a,projectData:e,title:t,subtitle:s,projectid:u,shareid:i,artwork:o,goToProject:m,fetchDetectedPlayer:_,resetDetectedPlayer:S}}const Dt={key:1},Ft={key:"preferences"},Wt={key:"file-meta",class:"d-flex s-caption justify-space-between s-text-secondary mb-8 mx-2 mt-3"},$t={key:0,class:"d-flex flex-column align-center mt-14"},Rt=N({__name:"index",setup(n){const l=ce(),{watermarkingEnabled:a,checkAndPrompt:e}=te();Me().watermarkingViewed();const{title:t,subtitle:s,artwork:u,projectid:i,shareid:o,goToProject:m,fetchDetectedPlayer:_,resetDetectedPlayer:S}=It(),{file:w,status:p,waveformPeaks:d,detected:v,playerid:A,statusMessage:I,isRedacted:f,setFile:P,reset:T}=Et({canProceed:e,onDetected:async W=>{await _(W)},onReset:S});return(W,C)=>(h(),j(me,{"view-padding":"","clamp-width":""},{default:F(()=>[C[1]||(C[1]=k("h1",{class:"s-heading-xlg mb-2"},"Watermarking",-1)),y(Q,null,{default:F(()=>[r(a)?(h(),x("div",Dt,[y(Z,{title:"Trace a leak",subtitle:"Upload a leaked file to find the link it came from",class:"mb-6 mt-12"}),y(nt,{file:r(w),"waveform-peaks":r(d),analyzing:r(p)==="uploading"||r(p)==="detecting","show-analyze-another":r(p)==="completed"||r(p)==="error",onSelect:r(P),onAnalyzeAnother:r(T)},null,8,["file","waveform-peaks","analyzing","show-analyze-another","onSelect","onAnalyzeAnother"]),y(Q,null,{default:F(()=>[r(w)?(h(),x("div",Wt,[k("span",null,Y(r(w).name)+" \xB7 "+Y(r(l).bytesToString(r(w).size)),1),k("span",{class:ie({"s-text-tertiary":r(I)==="null","detected-message":r(p)==="completed"&&r(v)})},Y(r(I)),3)])):(h(),x("div",Ft,[y(ht)]))]),_:1}
1),r(p)==="completed"&&!r(v)?(h(),x("div",$t,C[0]||(C[0]=[k("h3",{class:"mb-1"},"No match found",-1),k("p",{class:"s-body s-text-secondary"}," This audio does not contain a watermark ",-1)]))):U("",!0),r(p)==="completed"&&r(v)?(h(),x(z,{key:1},[y(ut,{redacted:r(f)||!r(o),title:r(t),subtitle:r(s),artwork:r(u),onOpen:r(m)},null,8,["redacted","title","subtitle","artwork","onOpen"]),!r(f)&&r(i)&&r(A)?(h(),j(yt,{key:0,projectid:r(i),playerid:r(A),"fallback-label":r(t)},null,8,["projectid","playerid","fallback-label"])):U("",!0)],64)):U("",!0)])):(h(),j(gt,{key:0}))]),_:1})]),_:1}))}});const ha=ee(Rt,[["__scopeId","data-v-1c3edaf2"]]);export{ha as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.