مطالب
معرفی برنامه‌ی Subtitle Tools

این روزها زیرنویس‌های فارسی فیلم‌های روز دنیا را راحت می‌شود در اینترنت یافت، اما مشکلات زیادی هم به همراه این نوع فایل‌ها وجود دارند:
- گاها با فیلم دریافت شده هماهنگ نیستند.
- عموما با فرمت windows-1256 تهیه می‌شوند که برای استفاده از آن‌ها در سیستم‌های مختلف بهتر است به UTF8 تبدیل شوند.
- اکثر برنامه‌های موجود برای کار با زیر نویس‌ها و ویرایش آن‌ها، درکی از یونیکد ندارند.
- عموما نیاز است جهت استفاده از آن‌ها در یک جمع، تعدادی از سطور آن‌ها را با حفظ شماره بندی فایل، حذف کرد!
و ...

به همین جهت نیاز به یک برنامه‌ی جمع و جور جهت کار با زیر نویس‌ها داشتم که نتیجه‌ی آن تهیه‌ی برنامه‌ی زیر شد:

الف) تغییر encoding فایل دریافتی به UTF-8
هنگام گشودن اکثر فایل‌های زیر نویس فارسی با تصویر زیر روبرو خواهید شد:



برای تبدیل آن به فرمت یونیکد تنها کافی است بر روی دکمه‌ی To UTF-8 کلیک کنید. در این حالت نتیجه به صورت زیر خواهد بود:



ب) هماهنگ سازی زیر نویس با فیلم دریافتی
ممکن است دیالوگ‌های زیر نویس دریافتی شما به اندازه‌ی مدت زمان خاصی، از دیالوگ‌های فیلم در حال پخش، عقب‌تر یا جلوتر باشند. در این حالت ابتدا باید این مدت زمان را با گوش فرا دادن به ابتدای فیلم و مقایسه‌ی آن با اولین شماره‌ی زیرنویس، پیدا کنید. مثلا پس از بررسی متوجه شده‌اید که به کلیه زمان‌های زیرنویس جاری باید 7 ثانیه اضافه گردد. اینکار را مطابق تصویر ذیل می‌توان انجام داد:



ج) یکی کردن زمان‌های دو زیر نویس با هم
گاهی از اوقات مشکلات زمانی یک زیرنویس وخیم‌تر از مورد ب است. به این معنا که شماره‌های مختلف آن، زمان‌های کاملا بی‌ربطی داشته و به صورت هماهنگ، قابل افزایش یا کاهش نیستند. در این حالت ابتدا زیر نویس مورد نظر را در برنامه باز کنید. سپس یک زیر نویس خوب انگلیسی هماهنگ با فیلم را نیز پیدا کنید و از طریق دکمه‌ی Merge times به برنامه معرفی نمائید. در این حالت به صورت خودکار زمان‌های صحیح از زیر نویس دوم به زیر نویس اول منتقل خواهند شد.

د) یکی کردن دو فایل زیر نویس با هم
ممکن است فیلم دریافتی تنها از یک فایل تشکیل شده باشد، اما شما فقط توانسته‌اید زیر نویس مرتبط با نگارش دو سی دی این فیلم را پیدا کنید. بنابراین نیاز است تا این دو فایل زیر نویس یکی شوند با این شرط که زمان‌های سی دی دوم از انتهای سی دی اول در فایل نهایی یکی شده‌ی تولیدی شروع گردد.
برای این منظور ابتدا فایل زیرنویس سی دی اول را در برنامه باز کرده و سپس به گزینه‌ی join files در برنامه مراجعه کنید. در اینجا ابتدا مسیر فایل زیرنویس سی دی 2 را مشخص نمائید. برنامه سعی خواهد کرد تا زمان آغاز قسمت دوم را بر اساس آخرین زمان سی دی اول و اولین زمان سی دی دوم حدس بزند و نمایش دهد. یا می‌توانید این مقدار پیش فرض را پذیرفته و بر روی دکمه‌ی join کلیک نمائید و یا امکان تغییر دستی آن هم میسر است.



ه) حذف و یا ویرایش ردیف‌ها
به دلایل نامشخصی اشخاصی که سعی در ترجمه‌ی زیرنویس‌ها می‌کنند عموما علاقمندند که به متن اصلی وفادار بمانند. به همین دلیل نیاز به جرح و تعدیل زیرنویس‌های تهیه شده برای نمایش در یک جمع خانوادگی وجود دارد. گزینه‌ی جستجوی موجود در بالای ردیف‌های زیرنویس باز شده در برنامه، امکان نمایش ردیف‌هایی را که حاوی متن وارد شده است، به صورت خودکار دارد.



در این حالت اگر نیاز است سطری حذف شود، آن‌را انتخاب نموده و بر روی دکمه‌ی Delete row کلیک نمائید. در این حالت علاوه بر حذف ردیف، کلیه شماره‌های موجود در زیر نویس نیز به صورت خودکار مجددا تولید و مرتب خواهند شد. (کلیک راست بر روی هر ردیف نیز این گزینه‌ را نمایش می‌دهد)
یا اگر مشغول به ویرایش متنی شدید، پس از ویرایش، کلیک کردن بر روی دکمه‌ی Save را فراموش نکنید (در حالت حذف نیازی به اینکار نیست).

ز) پیدا کردن زیرنویس یک فایل بر اساس امضای دیجیتال آن
سایت opensubtitles.org یک API را جهت پیدا کردن زیرنویسی مطابق با هش یک فایل ویدیویی ارائه داده است، که در برنامه‌ی جاری، کلاینتی برای آن تهیه شده است:



فقط کافی است فایل ویدیویی خود را در این قسمت انتخاب نمائید. برنامه هش فایل را محاسبه کرده و سپس با کمک سرویس XML-RPC سایت opensubtitles.org سعی در یافتن زیرنویس هماهنگ با آن خواهد کرد. در اینجا دیگر مهم نیست نام فایل انتخابی چیست؛ امضای دیجیتال آن مهم است. برای دریافت موارد مورد نظر، ابتدا آن‌ها را تیک زده و سپس بر روی دکمه‌ی دریافت کلیک کنید. کلیک راست بر روی ردیف مورد نظر نیز این امکان دریافت را لحاظ کرده است.
همچنین قسمتی هم برای آپلود زیرنویس به این سایت پیش بینی شده است (لطفا مصرف کننده‌ی صرف یا به قولی لیچر نباشید!)



در اینجا انتخاب فایل ویدیویی، فایل زیرنویس هماهنگ با آن و همچنین زبان زیر نویس الزامی است. از فایل ویدیویی جهت محاسبه‌ی هش آن برای یافتن ساده‌تر زیرنویس‌ها در دفعات آتی استفاده می‌گردد.

پیشنیاز استفاده از این برنامه، نصب دات نت فریم ورک 4 است که اگر از ویندوز 7 استفاده می‌کنید، جزو به روز رسانی‌های اختیاری آن است و در حالت کلی نسخه‌ی کامل 32 بیتی و 64 بیتی آن از این آدرس قابل دریافت است.


مطالب
توسعه برنامه‌های Cross Platform با Xamarin Forms & Bit Framework - قسمت نهم
در قسمت‌های قبل یاد گرفتید که چطور View و View Model را در متد RegisterTypes در App.xaml.cs به یکدیگر وصل کرده و به آن‌ها یک اسم دهید و با Navigation Service آن‌ها را در حالت‌های مختلف مثل Navigation Page و Master Detail و Popup و ... باز کنید و بین صفحات جابجا شوید.
در View‌ها دو مورد را به صورت ابتدایی توضیح دادیم، Binding و Command. در این قسمت وارد جزئیات می‌شویم.

Command قطعه‌ای کد در View Model است (عموما یک متد CSharp ای) که در View می‌تواند مورد استفاده قرار گیرد. برای این که کلیک بر روی یک دکمه، متد مربوطه در View Model را اجرا کند، آن را درون یک BitDelegateCommand قرار دادیم و به Command دکمه Bind کردیم.
می‌دانیم که Button، بجز کلیک، دارای Event‌های دیگری نیز هست. علاوه بر این، ممکن است بجای کلیک دکمه، بخواهیم زمانیکه روی یک عکس عمل Swipe انجام می‌شود، کاری در سمت View Model انجام شود.
برای حل این مشکل از Event To Command و Gesture Recognizer استفاده می‌کنیم. مورد اول همانطور که از نام‌اش پیداست، وظیفه آن اتصال بر قرار کردن بین یک Event و یک Command است و دومی نیز برای مسائلی چون Swipe - Tap - Pan - Pinch و ... بکار می‌رود.
در کد پایین که می‌تواند در HelloWorldView.xaml در پروژه XamApp نیز تست شود، یکبار Command دکمه را Bind کرده‌ایم و یکبار Clicked Event آن را، که البته نتیجه یکی است! به جای نام Clicked می‌توان نام هر یک از Event‌‌ها را نوشت. همچنین این کار بجز Button، بر روی باقی کنترل‌ها نیز کار می‌کند.
        <Button Command="{Binding IncreaseStepsCountCommand}" Text="Button with command binding" />
        <Button Text="Button with event to command">
            <Button.Behaviors>
                <prismBehaviors:EventToCommandBehavior Command="{Binding IncreaseStepsCountCommand}" EventName="Clicked" />
            </Button.Behaviors>
        </Button>
همانطور که می‌بینید، EventToCommandBehavior که توسط Prism ارائه شده‌است، به Behavior‌های Button اضافه شده‌است. هر Behavior، رفتاری خاص را به کنترل‌های شما اضافه می‌کند و امکان نوشتن Custom behavior نیز وجود دارد که از موضوع این بحث خارج است.

prismBehaviors در بالای فایل Xaml به شکل زیر تعریف شده است:
xmlns:prismBehaviors="clr-namespace:Prism.Behaviors;assembly=Prism.Forms"
این عمل معادل using نوشتن در بالای فایل‌های CSharp است و می‌گوید که EventToCommandBehavior در کدام namespace و dll است. وقتی این کار را می‌کنید، می‌توانید در Xaml به تمامی کلاس‌های آن namespace دسترسی داشته باشید.

در همان مثال HelloWorldView.xaml، یک Label بود که تعداد زده شدن دکمه را نشان می‌داد. اگر بخواهیم وقتی روی آن Label به سمت چپ Swipe می‌کنیم نیز Command مربوطه اجرا شود، خواهیم داشت:
        <Label Text="{Binding StepsCount, StringFormat='{}Button tapped {0} times!'}">
            <Label.GestureRecognizers>
                <SwipeGestureRecognizer Command="{Binding IncreaseStepsCountCommand}" Direction="Left" />
            </Label.GestureRecognizers>
        </Label>
در صورتیکه قصد تست بر روی Windows-UWP را دارید و صفحه نمایش لمسی ندارید، مطابق با آموزش قسمت Windows همین سری آموزشی، بر روی Simulator خروجی بگیرید.

در مورد Command، مطالبی چون Command Parameter و Event Args Parameter Path و Event Args Converter باقی می‌مانند که در قسمت‌های بعدی به آن‌ها نیز خواهیم پرداخت. ولی به صورت کلی در نظر داشته باشید که جای منطق برنامه، در سمت View Model است و اگر در سناریویی نمی‌دانستید که چگونه در واکنش به تغییری در View، در سمت View Model کاری کنید، می‌توانید همینجا سوال خود را بپرسید.

Binding نیز همان طور که تا الان متوجه شده‌اید، باعث اتصال دو چیز به یک دیگر می‌شود. وقتی می‌نویسیم:
<Label Text="{Binding StepsCount, StringFormat='{}Button tapped {0} times!'}" />
داریم Text را که یک Property در Label در View است، به StepsCount که یک Property در View Model است، وصل می‌کنیم.
هر Binding یک Source دارد. به صورت پیش فرض، چون داریم از Prism استفاده می‌کنیم، تمامی Binding‌ها در View به صورت پیش فرض به View Model اشاره می‌کنند؛ مگر اینکه چیز دیگری بگوییم. برای مثال، اگر بخواهیم یک Label داشته باشیم که متن یک Entry را نمایش می‌دهد، هیچ‌یک از این دو در View Model نیستند. پس در این Binding خاص، باید سورس را نیز مشخص کنیم:
        <Entry x:Name="MyEntry" />
        <Label Text="{Binding Text, Source={x:Reference MyEntry}}" />
این باعث می‌شود که Text، که یک Property در Label است، به Text، که یک Property در کنترلی با نام MyEntry است، وصل شود.

x:DataType
Binding‌ها به صورت پیش فرض، در زمان اجرا و با کمک Reflection کار می‌کنند؛ این مهم دو مسئله را ایجاد می‌کند:
1- اگر در View، نام Property مد نظر در View Model را به اشتباه بنویسید، تا زمانیکه برنامه را اجرا نکنید و وارد آن فرم نشوید، متوجه مشکل دار بودن ماجرا نمی‌شوید و وقتی در View Model نام یک Property را عوض می‌کنید، در سمت View در هنگام Build خطایی نمی‌گیرید.
2- Reflection چیز خوبی است و برخی سناریوها بدون آن خیلی سخت پیاده سازی می‌شوند؛ ولی Reflection سربار کارآیی دارد و بهتر است در صورت امکان از آن پرهیز شود.
برای حل این مشکل در Xamarin Forms امکانی به نام x:DataType معرفی شده‌است که در View می‌گویید که Source چه کلاسی است، که قاعدتا View Model است. برای این کار داریم:
<ContentPage
...
    xmlns:vm="clr-namespace:XamApp.ViewModels"
    x:DataType="vm:HelloWorldViewModel">
با این روش، هر دو مشکل فوق حل می‌شوند و هم خطای زمان Build برای Binding‌های اشتباه خواهیم داشت و هم بدون Reflection از Binding‌ها استفاده می‌کنیم که بهبود سرعت برنامه را در بر دارد.

INotifyPropertyChanged
در مثال XamApp، وقتی روی دکمه کلیک می‌کنیم، مقدار StepsCount را که یک Property در View Model است، یکی یکی افزایش می‌دهیم. این Property در View به Label بایند شده‌است. وقتی مقداری در View Model که سورس Binding ما محسوب می‌شود رخ می‌دهد، View چگونه خبر دار می‌شود؟
هر کلاسی که بخواهد در Binding به عنوان Source استفاده شود (منجمله View Model)، می‌تواند یک interface را پیاده سازی کند؛ به نام INotifyPropertyChanged. همچنین تعریف یک Property نیز باید به این شکل باشد:
        private int _StepsCount;
        public int StepsCount
        {
            get => _StepsCount;
            set => SetProperty(ref _StepsCount, value);
        }
طبیعتا این کد که در سناریوهایی می‌تواند حتی پیچیده‌تر شود، جالب نیست و برای همین ما از  PropertyChanged.Fody استفاده کرده‌ایم که در زمان Build، خودش همه مسائل را مدیریت می‌کند و کد فوق به سادگی می‌تواند به صورت زیر نوشته شود:
public int StepsCount { get; set; }
به صفحه GitHub این کتابخانه مراجعه کنید و با سایر امکانات فوق العاده‌ی آن آشنا شوید!
در Binding، موارد دیگری چون Value Converters و Relative Source نیز وجود دارند که در ادامه با آنها آشنا می‌شویم. اگر در Binding نیز مشکلی دارید، می‌توانید همینجا نیز بپرسید.
مطالب
نحوه اعلام وجود وبلاگی!

گاهی از اوقات بعضی از وبلاگ‌ نویس‌ها را می‌بینم که مدتی تلاش می‌کنند و بعد دست از کار می‌کشند و خداحافظ. مهم‌ترین علت آن احساس عدم توجه از طرف خوانندگان است. این عدم توجه هم از این‌جا ناشی می‌شود که کسی از وجود آن‌ها خبری ندارد.
یک وبلاگ با موضوع علمی راه انداخته‌اید؟ یک سایت در زمینه IT فراهم کرده‌اید؟ لطفا به یکی از سایت‌های زیر مراجعه کرده و اعلام وجود کنید!


من اکثر سایت‌های مرتبط جدید را از همین طریق کشف می‌کنم!


مطالب
خودمیزبانی ماژول های Nancy
در ادامه بررسی پروژه Nancy، در این مطلب به میزبانی پروژه‌های Nancy بدون نیاز به Asp.net می‌پردازیم. به این معنی که برنامه اجرایی که شما می‌نویسید خود یک سرور ایجاد می‌کند و کاربر با وارد کردن آدرس دستگاه شما در مرورگر خود، صفحات و ماژول‌های طراحی شده توسط شما را مشاهده می‌کند.
از کاربردهای چنین سیستمی به سایت‌های قابل حمل، و یا ارائه خدمات یک نرم افزار بر روی صفحات html می‌توان اشاره کرد. مثل گوگل دسکتاپ و یا گزارشات برخی سرویس‌های ویندوزی و یا حتی تنظیم یک سخت افزار متصل به سیستم از روی شبکه. یک ایده جالب می‌تواند ارسال اس ام اس از طریق شبکه و با جی اس ام مودم باشد. که به عنوان مثال کاربران با ورود به یک صفحه و ثبت پیام بتوانند از طریق جی اس ام مودم متصل به سرور آن را ارسال کنند. با یک مثال ساده ادامه می‌دهیم.

برای شروع یک پروژه از نوع Console بسازید و در Package manager کتابخانه Nancy.Hosting.Self را نصب کنید.
حالا یک ماژول جدید به نام TestModule.cs به پروژه اضافه می‌کنیم.
public class TestModule:NancyModule
{
 public TestModule()
 {
 Get["/"] = x=> { return "It is a test for nancy self hosting."; };

 }
}

حالا وارد program.cs شده و در متدMain کد زیر را می‌نویسیم:
var selfHost = new NancyHost(new Uri("http://localhost:12345"));
selfHost.Start();
Console.ReadKey();
selfHost.Stop();

در خط اول پورتی که منتظر دریافت درخواست‌های کاربران است را برابر 12345 قرار می‌دهیم. بنابراین برای تست این کد باید در مرورگر آدرس

http://localhost:12345 را تایپ کنید. اگر بخواهیم کاربر عدد انتهایی را وارد نکند باید از پورت 80 استفاده کنیم که پیش فرض http است ولی اکثرا در سیستم برنامه نویس‌ها توسط IIS مشغول می‌باشد.
در خط بعد سرور را اجرا کرده ایم و برنامه را به حالت انتظار برای فشرده شدن کلیدی در کنسول برده ایم.
وقتی کلیدی در کنسول فشرده شود سرور به حالت توقف می‌رود و اجرای برنامه پایان می‌یابد.
Nancy امکانات دیگری هم دارد. به عنوان مثال می‌توان برای طراحی نمای ماژول‌ها از موتور‌های دید استفاده کرد (ViewEngines). موتورهایی مثل Razor و ... . در صورت علاقمندی دوستان، در این باره هم خواهم نگاشت. 
مطالب
تفاوت‌های یک برنامه نویس کارمند با یک برنامه نویس علاقمند

اگر در یک محیط کاری به برنامه نویس‌ها دقت کنید دو گروه را به وضوح می‌توان تمایز داد. کسانی که برنامه نویسی می‌کنند تا اموراتشان بگذرد و کسانی که واقعا علاقمند به کارشان و دنیای برنامه نویسی هستند. به گروه اول می‌توان IT worker نام داد و گروه دوم را Software developer نامید.
جدول ذیل تفاوت‌های این دو گروه را بر می‌شمارد:

IT Workers Software developers
عموما 5 تا 9 ساعت در یک شرکت کار می‌کنند. عموما 5 تا 9 ساعت در یک شرکت کار کرده و پس از مراجعت به منزل بر روی پروژه‌های شخصی کار می‌کنند.
با اینکه هنوز در همان شرکت مشغول به کار است همیشه مشغول نق زدن است. احتمالا شاید بتواند همان موقعیت کاری را در یک شرکت دیگر نیز کسب کند. تا زمانیکه شغل فعلی برای او جذابیت دارد به آن ادامه خواهد داد و ترسی از حضور در شرکت‌های دیگر ندارد.
تنها محل یادگیری او همان پروژه‌هایی است که در شرکت وجود دارند یا مشغول به کار بر روی آن‌ها است. دید کاری و آموزشی او تنها به همین موارد خلاصه می‌شود. به صورت مداوم مشغول خواندن بلاگ‌ها، کتاب‌های جدید و فراگیری نحوه‌ی استفاده از برنامه‌های جدید می‌باشد.
عموما و اکثریت آن‌ها فقط به خاطر کلاس کاری به این رشته روی آورده‌اند و نه اصل کار مربوطه. به شدت علاقمند به بهبود روش‌های توسعه کاری و همچنین بهبود وضعیت خویش هستند.
اگر احتمالا بلاگی داشته باشند تنها به توضیح همان نق زدن‌های رایج در محیط کار می‌پردازند. از بلاگ خود در جهت توضیح تجارب کاری و کمک به ارتقای سایر همکاران خود استفاده می‌کنند.
اگر دانشی را کسب می‌کنند تنها محل عرضه‌ی آن جهت پز دادن پیش مدیر پروژه خواهد بود. بسیار با معلومات اما افتاده حال هستند.
از تغییرات مداوم دنیای IT که در آن قرار دارند هراسان هستند. مدام نق می‌زنند که مگر فاکس پروی 2.6 چه مشکلی دارد که باید از NHibernate استفاده کنند؟!
این نوع افراد همیشه می‌گویند که وقت ندارند مطالب جدید را بیاموزند و میل به تحجر و مقاومت در برابر تغییرات در آن‌ها بسیار زیاد است.
در تغییرات روی داده در دنیای IT سهیم بوده و جزئی از آن هستند.
زمانیکه قرار است یک قطعه کد اس کیوال را نمایش دهند از یک برچسب ساده یا یک تکست باکس استفاده می‌کنند. در حدی که فقط به قولی برنامه "کار کند". در همان حدی کار می‌کنند که به آن‌ها حقوق می‌دهند. نه بیشتر. چند روز وقت می‌گذارند و با روش‌های مختلف syntax highlighting و نمایش زیبای کد آشنا می‌شوند تا کاری را که ارائه می‌دهند مزه‌ی غذای مانده‌ی چند روز قبل را ندهد.

برای مطالعه بیشتر
+ و + و +

مطالب
لینک‌های هفته اول دی

وبلاگ‌ها و سایت‌های ایرانی

امنیت



ASP. Net


طراحی وب

PHP


اس‌کیوال سرور


سی شارپ


عمومی دات نت


مسایل اجتماعی و انسانی برنامه نویسی


کتاب‌های رایگان جدید


متفرقه
  • آهن بجای کروم! (یک برنامه نویس آلمانی قسمت‌هایی از مرورگر کروم را که در جهت جمع آوری اطلاعات برای گوگل بکار می‌رفته، حذف کرده و مرورگر دیگری به نام آهن را ارائه داده است!)